xml_AST.cc: add missing include
[ppn.git] / domain.cc
blobb1093f792b9d286d9d593738d9331039e2a083c7
1 #include "suif_inc.h"
2 #include <algorithm>
3 #include <sstream>
4 #include "domain.h"
6 const char * k_static_root;
7 const char * k_stmt;
8 const char * k_if_annote;
9 const char * k_domain_symtab;
10 const char * k_iteration_domain;
11 const char *k_for_annote;
12 const char *k_array_bounds;
13 const char *k_set_in_scope;
15 void symtab_ann::add_var(var_sym *var)
17 if (vars.find(var) == vars.end())
18 vars[var] = new Param_Iterator(var->name());
21 void symtab_ann::add_var(named_lin_ineq *nlq)
23 if (!nlq)
24 return;
25 for (int i = 1; i < nlq->n(); ++i)
26 add_var(nlq->names()[i].var());
29 var_sym *symtab_ann::create_tmp()
31 var_sym *tmp = symtab->new_unique_var(type_signed);
32 add_var(tmp);
33 vars[tmp]->temp = true;
34 return tmp;
37 void
38 domain_constructor::recurse(tree_node * tn)
40 unsigned n = tn->num_child_lists();
41 for (unsigned i = 0; i < n; ++i)
42 construct(tn->child_list_num(i));
45 SRelation * domain_constructor::reorder(SRelation * c)
47 Relation r = copy(*(Relation*)c);
48 r = Extend_Set(r, level);
49 for (int i = 0; i < level; ++i) {
50 EQ_Handle e = r.and_with_EQ();
51 e.update_coef(r.get_local(sa->vars[its[i]]), -1);
52 e.update_coef(r.set_var(i+1), 1);
53 r = Project(r, sa->vars[its[i]]);
55 return new SRelation(r, sa);
58 /* Replace c, with only named constraints, by an actual
59 * map from the iterators and nested accesses to the array dimensions.
61 * Each of the input and output dimensions is equated to the
62 * corresponding parameter in c.
64 * output is the number of output variables (array dimensions)
66 SRelation *domain_constructor::reorder(SRelation *c,
67 const std::vector<var_sym *> &nested_vars, int output)
69 Relation r = copy(*(Relation*)c);
70 r = Extend_Domain(r, level + nested_vars.size());
71 r = Extend_Range(r, output);
73 for (int i = 0; i < level; ++i) {
74 EQ_Handle e = r.and_with_EQ();
75 e.update_coef(r.get_local(sa->vars[its[i]]), -1);
76 e.update_coef(r.input_var(1 + i), 1);
77 r = Project(r, sa->vars[its[i]]);
80 for (int i = 0; i < nested_vars.size(); ++i) {
81 EQ_Handle e = r.and_with_EQ();
82 e.update_coef(r.get_local(sa->vars[nested_vars[i]]), -1);
83 e.update_coef(r.input_var(1 + level + i), 1);
84 r = Project(r, sa->vars[nested_vars[i]]);
87 for (int i = 0; i < output; ++i) {
88 EQ_Handle e = r.and_with_EQ();
89 e.update_coef(r.get_local(sa->vars[out[i]]), -1);
90 e.update_coef(r.output_var(1 + i), 1);
91 r = Project(r, sa->vars[out[i]]);
94 SRelation *s = new SRelation(r, sa, c->nested);
95 delete c;
97 return s;
100 /* In the process of extracting a messy index, update the equality
101 * encoded in the first two inequalities of "nli" with
102 * "f" times the result of the expression "in".
104 * If "in" represents an array access, then the access is added
105 * to "nested" and a new variable and a new column are constructed
106 * that correspond to this nested access.
108 * If "in" represents an integer division "d = f/m", with m a constant,
109 * then we first construct a relation for d = f. The first two rows
110 * then contain
111 * -d + f >= 0
112 * d - f >= 0
113 * These are updated to
114 * -m d + f >= 0
115 * m d - f + m - 1 >= 0
117 * i.e.,
118 * m d <= f <= m d + m - 1
120 * Finally, the original equality is updated with f * d and the above
121 * constraints are added to the constraint set.
123 void domain_constructor::extract_messy_index(SRelation *map,
124 Constraint_Handle &h, instruction *in, int f)
126 switch (in->opcode()) {
127 case io_ldc: {
128 in_ldc *ins = dynamic_cast<in_ldc *>(in);
129 f *= ins->value().integer();
130 h.update_const(f);
131 break;
133 case io_add:
134 extract_messy_index(map, h, in->src_op(0), f);
135 extract_messy_index(map, h, in->src_op(1), f);
136 break;
137 case io_sub:
138 extract_messy_index(map, h, in->src_op(0), f);
139 extract_messy_index(map, h, in->src_op(1), -f);
140 break;
141 case io_neg:
142 extract_messy_index(map, h, in->src_op(0), -f);
143 break;
144 case io_lod: {
145 stmt_node *node;
146 operand r = in->src_op(0);
147 node = extract_stmt_node(r, false);
148 assert(node);
149 node->var = sa->create_tmp();
150 node->op = r;
151 map->nested.push_back(node);
152 h.update_coef(map->get_local(sa->vars[node->var]), f);
153 break;
155 case io_mul: {
156 operand op1 = in->src_op(0);
157 operand op2 = in->src_op(1);
158 if (op1.kind() == OPER_INSTR &&
159 op1.instr()->opcode() == io_ldc) {
160 in_ldc *ins = dynamic_cast<in_ldc *>(op1.instr());
161 f *= ins->value().integer();
162 extract_messy_index(map, h, op2, f);
163 break;
165 if (op2.kind() == OPER_INSTR &&
166 op2.instr()->opcode() == io_ldc) {
167 in_ldc *ins = dynamic_cast<in_ldc *>(op2.instr());
168 f *= ins->value().integer();
169 extract_messy_index(map, h, op1, f);
170 break;
172 in->print(stderr);
173 assert(0);
175 case io_div: {
176 operand op2 = in->src_op(1);
177 assert(op2.kind() == OPER_INSTR &&
178 op2.instr()->opcode() == io_ldc);
179 in_ldc *ins = dynamic_cast<in_ldc *>(op2.instr());
180 int mod = ins->value().integer();
181 assert(mod > 0);
183 Variable_ID q = map->e->declare();
184 h.update_coef(q, f);
186 /* e - m f >= 0 */
187 GEQ_Handle g1 = map->f->add_GEQ();
188 g1.update_coef(q, -mod);
189 extract_messy_index(map, g1, in->src_op(0), 1);
191 /* -e + m f + m-1 >= 0 */
192 GEQ_Handle g2 = map->f->add_GEQ();
193 g2.update_coef(q, mod);
194 g2.update_const(mod - 1);
195 extract_messy_index(map, g2, in->src_op(0), -1);
197 break;
199 default:
200 in->print(stderr);
201 assert(0);
205 static bool data_dependent(var_sym *v, symtab_ann *sa)
207 return sa->vars.find(v) != sa->vars.end() &&
208 sa->vars[v]->assigned && !sa->vars[v]->iterator;
211 /* Return true if any variable in the index expression
212 * has been assigned a value and is not currently used as
213 * an iterator.
215 static bool data_dependent(access_vector *av, symtab_ann *sa)
217 if (av->too_messy)
218 return false;
219 access_list_iter iter(&av->conregs);
220 while (!iter.is_empty()) {
221 var_sym *v = (var_sym *)iter.step()->var();
222 if (data_dependent(v, sa))
223 return true;
225 return false;
228 /* In the process of extracting a messy index, update the equality
229 * encoded in the first two inequalities of "nli" with
230 * "f" times the value of "op".
232 * If "op" is an expression, update the equality with f times the
233 * result of the expression.
234 * If "op" is a symbol, update the corresponding column in the equality.
236 void domain_constructor::extract_messy_index(SRelation *map,
237 Constraint_Handle &h, operand op, int f)
239 if (op.is_expr()) {
240 extract_messy_index(map, h, op.instr(), f);
241 return;
244 assert(op.is_symbol());
245 assert(!op.symbol()->type()->is_ptr());
247 if (data_dependent(op.symbol(), sa)) {
248 stmt_node *node;
249 node = extract_stmt_node(op, false);
250 assert(node);
251 node->var = sa->create_tmp();
252 node->op = op;
253 map->nested.push_back(node);
254 h.update_coef(map->get_local(sa->vars[node->var]), f);
255 } else {
256 sa->add_var(op.symbol());
257 h.update_coef(map->get_local(sa->vars[op.symbol()]), f);
261 /* Construct and return an access relation for some kinds of messy
262 * indices. In particular, handle indices with nested array accesses.
263 * If anything unexpected appears, we currently just abort.
264 * Any nested array access is appended to "nested".
265 * "out" is the variable that represents the array index "index"
266 * in the returned access relation.
268 * The first two rows of the returned named_lin_ineq are two
269 * opposite inequalities representing an equality.
271 SRelation *domain_constructor::extract_messy_index(operand index, var_sym *out)
273 int pos;
275 named_lin_ineq *nli = new named_lin_ineq;
276 SRelation *map = new SRelation(sa, nli);
277 EQ_Handle g = map->f->add_EQ();
278 g.update_coef(map->get_local(sa->vars[out]), -1);
279 extract_messy_index(map, g, index, 1);
280 return map;
283 stmt_access *domain_constructor::create_access(dep_instr_annote *di, bool write)
285 instruction *in = di->my_instr;
286 assert(in->opcode() == io_array);
287 in_array *ina = (in_array *)in;
288 assert(ina->base_op().is_instr());
289 var_sym *array;
290 switch (ina->base_op().instr()->opcode()) {
291 case io_ldc: {
292 in_ldc *ldc = (in_ldc *) ina->base_op().instr();
293 assert(ldc->value().kind() == im_symbol);
294 assert(ldc->value().symbol()->kind() == SYM_VAR);
295 array = (var_sym *)ldc->value().symbol();
296 break;
298 case io_cvt: {
299 instruction *in = ina->base_op().instr();
300 assert(in->src_op(0).kind() == OPER_SYM);
301 assert(in->src_op(0).symbol()->kind() == SYM_VAR);
302 array = (var_sym *)in->src_op(0).symbol();
303 break;
305 default:
306 assert(0);
309 named_lin_ineq *nlq = new named_lin_ineq();
310 SRelation *map = new SRelation(sa, nlq);
311 array_info_iter iter(di->ai);
312 int i;
313 for(i = 0; !iter.is_empty(); ++i) {
314 if (i >= out.size())
315 out.push_back(sa->create_tmp());
317 access_vector * av = iter.step();
318 bool messy = av->too_messy || data_dependent(av, sa);
319 if (messy && !write) {
320 SRelation *old = map;
321 SRelation *m;
322 m = extract_messy_index(ina->index(i), out[i]);
323 map = map->Intersection(m);
324 delete m;
325 delete old;
326 continue;
328 if (messy)
329 in->print();
330 assert(!messy);
332 /* Treat all non-induction variables in access vector
333 * as parameters. However, if the variable has
334 * been assigned a value before, then it cannot be
335 * a parameter.
337 access_list_iter iter(&av->conregs);
338 while (!iter.is_empty()) {
339 var_sym *v = (var_sym *)iter.step()->var();
340 if (sa->vars.find(v) != sa->vars.end())
341 assert(!sa->vars[v]->assigned ||
342 sa->vars[v]->iterator);
343 sa->add_var(v);
346 map->intersect(named_lin_ineq::mk_named_lin_ineq(*av, out[i],
347 FALSE));
348 map->intersect(named_lin_ineq::mk_named_lin_ineq(*av, out[i],
349 TRUE));
352 return new stmt_access(write, map, array, i);
355 /* Returns stmt_access if it's an access already analyzed by SUIF */
356 stmt_access *domain_constructor::check_access(instruction *in, bool write)
358 dep_instr_annote *di =
359 (dep_instr_annote *)in->peek_annote(k_dep_instr_annote);
360 if (!di)
361 return NULL;
363 return create_access(di, write);
366 /* Is it ok to write to (write = true) or read from (write = false)
367 * variable scalar?
368 * It is not ok to write to a variable that is currently being used
369 * as an iterator.
370 * It is also not ok to read from a variable that is not an iterator
371 * and that has once been written (making it not a parameter), but
372 * that currently does not have a known value (because it has been
373 * used as an iterator after the last write).
375 static bool is_access_ok(symtab_ann *sa, var_sym *scalar, bool write)
377 Param_Iterator *var = sa->vars[scalar];
378 if (write && var->iterator)
379 return false;
380 if (!write && !var->iterator && !var->valid_for_read)
381 return false;
382 return true;
385 /* Check whether ct contains any invalid nodes or data dependent
386 * accesses.
387 * If so, then this condition tree shouldn't be considered as
388 * a known value.
390 static bool invalid_or_data_dependent(condition_tree *ct, symtab_ann *sa)
392 switch (ct->type) {
393 case ctt_invalid:
394 case ctt_lod:
395 return true;
396 case ctt_cst:
397 return false;
398 case ctt_add:
399 case ctt_sub:
400 return invalid_or_data_dependent(ct->left, sa) ||
401 invalid_or_data_dependent(ct->right, sa);
402 case ctt_mul:
403 return invalid_or_data_dependent(ct->right, sa);
404 case ctt_neg:
405 case ctt_rem:
406 case ctt_floord:
407 return invalid_or_data_dependent(ct->left, sa);
408 case ctt_sym:
409 return data_dependent(ct->var, sa);
411 assert(0);
414 /* Check whether ct contains any invalid nodes.
416 static bool invalid(condition_tree *ct, symtab_ann *sa)
418 switch (ct->type) {
419 case ctt_invalid:
420 return true;
421 case ctt_lod:
422 case ctt_cst:
423 case ctt_sym:
424 return false;
425 case ctt_add:
426 case ctt_sub:
427 case ctt_min:
428 case ctt_max:
429 return invalid(ct->left, sa) ||
430 invalid(ct->right, sa);
431 case ctt_mul:
432 return invalid(ct->right, sa);
433 case ctt_neg:
434 case ctt_rem:
435 case ctt_floord:
436 case ctt_ceild:
437 return invalid(ct->left, sa);
439 assert(0);
442 stmt_node *domain_constructor::extract_stmt_node(operand &op, bool write,
443 instruction *parent)
445 if (op.is_expr())
446 return extract_stmt_node(op.instr());
448 if (!op.is_symbol()) {
449 op.print(stderr);
450 assert(0);
453 if (op.symbol()->type()->is_ptr())
454 return NULL;
455 named_lin_ineq *a = new named_lin_ineq();
456 var_sym *array = op.symbol();
457 int output = 0;
458 bool iterator_access = false;
459 if (sa->vars.find(array) != sa->vars.end()) {
460 if (!is_access_ok(sa, array, write)) {
461 if (parent)
462 parent->print(stderr);
464 assert(is_access_ok(sa, array, write));
465 iterator_access = !sa->vars[array]->assigned ||
466 sa->vars[array]->iterator;
468 if (write) {
469 sa->add_var(array);
470 sa->vars[array]->assigned = true;
471 sa->vars[array]->value =
472 construct_condition_tree_expr(parent, verbose);
473 if (invalid(sa->vars[array]->value, sa)) {
474 delete sa->vars[array]->value;
475 sa->vars[array]->value = NULL;
476 } else {
477 if (scope)
478 scope->append_annote(k_set_in_scope, array);
479 sa->vars[array]->valid_for_read = true;
481 iterator_access = false;
483 if (iterator_access) {
484 /* an iterator or a parameter */
485 /* set inequalities to "out[0] = array */
486 if (out.size() == 0)
487 out.push_back(sa->create_tmp());
488 a->ineqs().init(2,1);
489 a->names().init(1);
490 a->add_col(name_table_entry(array), 1);
491 a->add_col(name_table_entry(out[0]), 2);
492 a->ineqs()[0][1] = 1;
493 a->ineqs()[0][2] = -1;
494 a->ineqs()[1][1] = -1;
495 a->ineqs()[1][2] = 1;
496 array = NULL;
497 output = 1;
499 SRelation *map = new SRelation(sa, a);
500 return new stmt_access(write, map, array, output);
503 static stmt *add_access(stmt *s, stmt_node *out)
505 stmt_access *acc = dynamic_cast<stmt_access *>(out);
506 if (!acc) {
507 delete s;
508 return NULL;
510 acc->write = true;
511 s->out.push_back(acc);
512 return s;
516 * Returns NULL if instruction is not ok
517 * Checks currently incomplete
519 stmt *domain_constructor::extract_stmt(tree_instr *t)
521 stmt_node *out = NULL;
522 instruction *i = t->instr();
523 stmt_node *node;
525 if (i->opcode() == io_str || i->opcode() == io_memcpy) {
526 out = extract_stmt_node(i->src_op(0).instr());
527 if (!out)
528 return NULL;
529 operand r = i->src_op(1);
530 node = extract_stmt_node(r, false);
531 } else
532 node = extract_stmt_node(i);
534 if (!node) {
535 if (out)
536 delete out;
537 return NULL;
540 stmt *s = new stmt;
541 s->tree = node;
543 if (out)
544 s = add_access(s, out);
545 if (!s)
546 return NULL;
548 for (unsigned n = 0; n < i->num_dsts(); n++) {
549 operand r = i->dst_op(n);
550 if (r.is_null())
551 continue;
552 stmt_node *dst = extract_stmt_node(r, true, i);
553 s = add_access(s, dst);
554 if (!s)
555 return NULL;
558 return s;
561 static char *immed2str(immed im)
563 std::ostringstream strm;
565 switch (im.kind()) {
566 case im_int:
567 strm << im.integer();
568 break;
569 case im_float:
570 strm << im.flt();
571 break;
572 default:
573 fprintf(stderr, "unsupported immed type: %d\n", im.kind());
574 assert(0);
577 return strdup(strm.str().c_str());
580 static const char *instr_name(instruction *i)
582 if (i->opcode() == io_cal) {
583 in_cal *cal = dynamic_cast<in_cal *>(i);
584 in_ldc *ldc = dynamic_cast<in_ldc *>(cal->addr_op().instr());
585 assert(ldc->value().symbol()->is_proc());
586 proc_sym *proc = dynamic_cast<proc_sym *>(ldc->value().symbol());
587 return proc->name();
589 if (i->opcode() == io_str || i->opcode() == io_cpy)
590 return "";
591 if (i->opcode() == io_ldc) {
592 in_ldc *ins = dynamic_cast<in_ldc *>(i);
593 return immed2str(ins->value());
595 if (i->opcode() == io_add)
596 return "+";
597 if (i->opcode() == io_sub)
598 return "-";
599 if (i->opcode() == io_mul)
600 return "*";
601 if (i->opcode() == io_div)
602 return "/";
603 if (i->opcode() == io_rem)
604 return "%";
605 if (i->opcode() == io_neg)
606 return "-";
607 if (i->opcode() == io_sl)
608 return "<";
609 fprintf(stderr, "unrecognized instruction\n");
610 i->print(stderr);
611 return NULL;
614 stmt_node *domain_constructor::extract_stmt_node(instruction *i)
616 stmt_node *node;
618 node = check_access(i, false);
619 if (node)
620 return node;
622 if (i->opcode() == io_lod) {
623 operand r = i->src_op(0);
624 return extract_stmt_node(r, false);
627 if (i->opcode() == io_cal) {
628 in_cal *cal = dynamic_cast<in_cal *>(i);
629 return extract_stmt_node_cal(cal);
632 const char *name = instr_name(i);
633 if (!name)
634 return NULL;
636 stmt_call *call = new stmt_call(name);
638 for (unsigned n = 0; n < i->num_srcs(); n++) {
639 operand r = i->src_op(n);
640 /* Second operand of io_cpy is null operand */
641 if (r.is_null())
642 continue;
643 node = extract_stmt_node(r, false);
644 if (!node) {
645 delete call;
646 return NULL;
648 call->arg.push_back(node);
651 return call;
654 stmt_node *domain_constructor::extract_stmt_node_cal(in_cal *cal)
656 const char *name = instr_name(cal);
657 if (!name)
658 return NULL;
660 stmt_call *call = new stmt_call(name);
662 in_ldc *ldc = dynamic_cast<in_ldc *>(cal->addr_op().instr());
663 assert(ldc->value().symbol()->is_proc());
664 proc_sym *proc = dynamic_cast<proc_sym *>(ldc->value().symbol());
665 func_type *type = proc->type();
666 if (!type->args_known()) {
667 type = type->clone();
668 type->set_num_args(cal->num_args());
669 proc->set_type(type);
670 for (unsigned n = 0; n < type->num_args(); ++n)
671 type->set_arg_type(n, type_signed);
672 type->set_return_type(type_signed);
673 tp->proc()->file()->parent()->globals()->add_type(type);
675 for (unsigned n = 0; n < type->num_args(); ++n) {
676 stmt_node *node;
677 type_node *atype = type->args_known() ? type->arg_type(n) : NULL;
678 operand op = cal->argument(n);
679 if (!atype || !atype->is_ptr()) {
680 node = extract_stmt_node(op, false);
681 if (!node) {
682 delete call;
683 return NULL;
685 call->arg.push_back(node);
686 continue;
688 /* if the function expects a pointer
689 * consider data of which the address is taken
690 * to be input if the type is pointer to const
691 * and output otherwise.
693 ptr_type *ptr = static_cast<ptr_type *>(atype);
694 type_node *base = ptr->ref_type();
695 boolean write = !base->is_const();
697 if (op.instr()->opcode() == io_cvt)
698 op = op.instr()->src_op(0);
699 node = check_access(op.instr(), write);
700 if (node) {
701 call->arg.push_back(node);
702 continue;
705 in_ldc *ldc = dynamic_cast<in_ldc *>(op.instr());
706 assert(ldc);
707 assert(ldc->value().kind() == im_symbol);
708 assert(ldc->value().symbol()->kind() == SYM_VAR);
709 var_sym *var = static_cast<var_sym*>(ldc->value().symbol());
711 named_lin_ineq *a = new named_lin_ineq();
712 SRelation *map = new SRelation(sa, a);
713 node = new stmt_access(write, map, var, 0);
714 call->arg.push_back(node);
717 return call;
720 void domain_constructor::set_prefix_and_iterator(int prefix_value, var_sym *iterator)
722 if (plevel >= prefix.size())
723 prefix.push_back(prefix_value);
724 else
725 prefix[plevel] = prefix_value;
727 if (!iterator && level < its.size() && its[level]->parent() == sa->symtab)
728 return;
729 if (!iterator)
730 iterator = sa->symtab->new_unique_var(type_signed);
731 if (level >= its.size())
732 its.push_back(iterator);
733 else
734 its[level] = iterator;
735 sa->add_var(its[level]);
736 sa->vars[its[level]]->iterator = true;
739 void domain_constructor::construct_broken_up_loop(for_ann *fa)
741 SRelation *oldc = c;
742 c = fa->bounds->Intersection(oldc);
744 set_prefix_and_iterator(-1, fa->iterator);
746 ++level;
747 ++plevel;
748 construct(fa->body);
749 --plevel;
750 --level;
752 delete c;
753 c = oldc;
756 /* Create 1D set with given lower and upper bounds.
758 static SRelation *set_from_bounds(int lb, int ub, symtab_ann *sa)
760 Relation r(1);
762 GEQ_Handle e1 = r.and_with_GEQ();
763 e1.update_coef(r.set_var(1), 1);
764 e1.update_const(-lb);
765 GEQ_Handle e2 = r.and_with_GEQ();
766 e2.update_coef(r.set_var(1), -1);
767 e2.update_const(ub);
769 return new SRelation(r, sa);
772 /* Convert integer or string immed to int.
773 * Return non-zero if immed is not a string or an integer.
775 static int immed_to_int(immed im, int *i)
777 switch (im.kind()) {
778 case im_int:
779 *i = im.integer();
780 return 0;
781 case im_string:
782 *i = strtol(im.string(), NULL, 0);
783 return 0;
785 return 1;
788 /* Given a "value_bounds" pragma, check that it is of the form
790 * #pragma value_bounds name_of_array lower_bound upper_bound
792 * where lower_bound and upper_bound may be integers or strings.
793 * Note that a minus sign followed by digits in a pragma is not interpreted
794 * as a negative number by SUIF.
795 * If so, add an SRelation annote to the array expressing the given bounds.
797 void domain_constructor::apply_value_bounds(annote *an)
799 immed_list *ims = an->immeds();
800 sym_node *sym;
801 int lb, ub;
803 if (ims->count() != 4)
804 goto error;
805 if ((*ims)[1].kind() != im_symbol)
806 goto error;
807 sym = (*ims)[1].symbol();
808 if (sym->kind() != SYM_VAR)
809 goto error;
810 if (immed_to_int((*ims)[2], &lb))
811 goto error;
812 if (immed_to_int((*ims)[3], &ub))
813 goto error;
814 sym->append_annote(k_array_bounds, set_from_bounds(lb, ub, sa));
816 return;
817 error:
818 fprintf(stderr, "invalid value_bounds pragma\n");
821 /* Check for any interesting pragmas associated to the given instruction.
822 * In particular, check for value_bounds pragmas.
824 void domain_constructor::check_pragmas(instruction *in)
826 const char *k_C_pragma = lexicon->enter("C pragma")->sp;
827 annote_list_iter anli(in->annotes());
828 while (!anli.is_empty()) {
829 annote *an = anli.step();
830 if (an->name() != k_C_pragma)
831 continue;
832 immed_list *ims = an->immeds();
833 if (!(*ims)[0].is_string())
834 continue;
835 if (strcmp((*ims)[0].string(), "value_bounds") == 0)
836 apply_value_bounds(an);
840 /* Construct an iteration domain annote from a stmt annote attached
841 * to obj and the current constraints on the iterators and attach
842 * the annote to obj.
843 * insn is the intruction that gave rise to the statement
844 * and may be NULL if there is no clearly identifiable such instruction.
846 void domain_constructor::add_iteration_domain(suif_object *obj,
847 instruction *insn)
849 stmt *s = (stmt *)obj->peek_annote(k_stmt);
851 s->reorder(this);
853 SRelation *o = reorder(c);
855 domain_ann *da;
856 int line = source_line_num(obj);
857 da = new domain_ann(insn, o, level, plevel, its, prefix, s, line);
858 obj->append_annote(k_iteration_domain, da);
861 void
862 domain_constructor::construct(tree_node * tn)
864 switch (tn->kind()) {
865 case TREE_INSTR: {
866 for_ann *fa = (for_ann *)tn->peek_annote(k_for_annote);
867 if (fa) {
868 construct_broken_up_loop(fa);
869 break;
871 tree_instr *in = (tree_instr*)tn;
872 switch (in->instr()->opcode()) {
873 case io_mrk:
874 check_pragmas(in->instr());
875 break;
876 default:
877 assert(0);
878 case io_memcpy:
879 case io_cpy:
880 case io_str:
881 case io_lod:
882 case io_cvt:
883 case io_ldc:
884 case io_add:
885 case io_sub:
886 case io_mul:
887 case io_div:
888 case io_rem:
889 case io_cal:
890 root = in->instr();
891 add_iteration_domain(root, root);
893 break;
895 case TREE_FOR: {
896 for_ann *fa = (for_ann *)tn->peek_annote(k_for_annote);
897 if (fa) {
898 construct_broken_up_loop(fa);
899 break;
901 SRelation * oldc = new SRelation(*c);
902 dep_for_annote * df =
903 (dep_for_annote *)tn->peek_annote(k_dep_for_annote);
904 tree_for * tf = df->my_for;
905 immed idx(tf->index());
906 c->intersect(named_lin_ineq::mk_named_lin_ineq(*df->lb, idx, TRUE));
907 c->intersect(named_lin_ineq::mk_named_lin_ineq(*df->ub, idx, FALSE));
909 set_prefix_and_iterator(-1, tf->index());
911 ++level;
912 ++plevel;
913 construct(tf->body());
914 --plevel;
915 --level;
917 delete c;
918 c = oldc;
919 break;
921 case TREE_LOOP: {
922 /* We only get here if the loop was determined to be a simple infinite loop */
923 SRelation * oldc = new SRelation(*c);
924 tree_loop *tl = static_cast<tree_loop *>(tn);
926 set_prefix_and_iterator(-1);
927 c->set_infinite(its[level]);
929 ++level;
930 ++plevel;
931 construct(tl->body());
932 --plevel;
933 --level;
935 delete c;
936 c = oldc;
937 break;
939 case TREE_IF: {
940 tree_if * ti = (tree_if *)tn;
941 SRelation * oldc = c;
943 if (tn->peek_annote(k_stmt)) {
944 add_iteration_domain(tn, NULL);
945 break;
948 SRelation * s = (SRelation *)tn->peek_annote(k_if_annote);
949 /* The if is not annotated, so it must be the second part
950 * of a broken down loop we discovered during the scan phase.
952 if (!s)
953 break;
954 c = s->Intersection(oldc);
956 construct(ti->then_part());
958 delete c;
960 if (ti->else_part()->is_empty()) {
961 c = oldc;
962 break;
965 c = oldc->Difference(s);
967 construct(ti->else_part());
969 delete c;
971 c = oldc;
972 break;
974 default:
975 recurse(tn);
976 break;
980 void
981 domain_constructor::construct(tree_node_list * tnl)
983 set_prefix_and_iterator(0);
985 tree_node_list_iter tnli(tnl);
986 for (int i = 0; !tnli.is_empty(); ++i) {
987 tree_node *t = tnli.step();
989 SRelation * oldc = new SRelation(*c);
991 if (oldstyle)
992 c->fix(its[level], i);
993 prefix[plevel] = i;
995 if (oldstyle)
996 ++level;
997 ++plevel;
998 construct(t);
999 --plevel;
1000 if (oldstyle)
1001 --level;
1003 delete c;
1004 c = oldc;
1008 void domain_constructor::visit(tree_node *t)
1010 if (!t->peek_annote(k_static_root))
1011 return;
1013 c = new SRelation(sa);
1014 level = 0;
1015 plevel = 0;
1016 construct(t);
1017 delete c;
1020 static void visit (tree_node *t, void *d)
1022 ((domain_constructor *)d)->visit(t);
1025 void domain_constructor::construct()
1027 tp->map(::visit, (void *) this);
1030 bool guard_constructor::fill_q(Constraint_Handle& h, condition_tree *ct, int mult)
1032 switch(ct->type) {
1033 case ctt_cst:
1034 h.update_const(mult * ct->val);
1035 break;
1036 case ctt_add:
1037 if (!fill_q(h, ct->left, mult))
1038 return false;
1039 if (!fill_q(h, ct->right, mult))
1040 return false;
1041 break;
1042 case ctt_sub:
1043 if (!fill_q(h, ct->left, mult))
1044 return false;
1045 if (!fill_q(h, ct->right, -mult))
1046 return false;
1047 break;
1048 case ctt_sym: {
1049 sa->add_var(ct->var);
1050 Param_Iterator *var = sa->vars[ct->var];
1051 if (var->value)
1052 return fill_q(h, var->value, mult);
1053 if (var->iterator || !var->assigned) {
1054 h.update_coef(s->get_local(sa->vars[ct->var]), mult);
1055 break;
1057 if (!dc)
1058 return false;
1059 stmt_node *node;
1060 operand op(ct->var);
1061 node = dc->extract_stmt_node(op, false);
1062 if (!node)
1063 return false;
1064 node->var = sa->create_tmp();
1065 node->op = op;
1066 s->nested.push_back(node);
1067 h.update_coef(s->get_local(sa->vars[node->var]), mult);
1068 break;
1070 case ctt_mul:
1071 assert(ct->left->type == ctt_cst);
1072 return fill_q(h, ct->right, mult * ct->left->val);
1073 case ctt_neg:
1074 if (!fill_q(h, ct->left, -mult))
1075 return false;
1076 break;
1077 case ctt_rem: {
1078 assert(ct->right->type == ctt_cst);
1079 int mod = ct->right->val;
1081 Variable_ID q = s->e->declare();
1082 Variable_ID r = s->e->declare();
1083 h.update_coef(r, mult);
1085 /* r >= 0 */
1086 GEQ_Handle g1 = s->f->add_GEQ();
1087 g1.update_coef(r, 1);
1089 /* r <= mod-1 */
1090 GEQ_Handle g2 = s->f->add_GEQ();
1091 g2.update_coef(r, -1);
1092 g2.update_const(mod-1);
1094 /* mod * q + r = op1 */
1095 EQ_Handle g3 = s->f->add_EQ();
1096 g3.update_coef(r, -1);
1097 g3.update_coef(q, -mod);
1098 if (!fill_q(g3, ct->left, 1))
1099 return false;
1100 break;
1102 case ctt_floord: {
1103 /* f = floor(e/m) */
1104 assert(ct->right->type == ctt_cst);
1105 int mod = ct->right->val;
1107 Variable_ID q = s->e->declare();
1108 h.update_coef(q, mult);
1110 /* e - m f >= 0 */
1111 GEQ_Handle g1 = s->f->add_GEQ();
1112 g1.update_coef(q, -mod);
1113 if (!fill_q(g1, ct->left, 1))
1114 return false;
1116 /* -e + m f + m-1 >= 0 */
1117 GEQ_Handle g2 = s->f->add_GEQ();
1118 g2.update_coef(q, mod);
1119 g2.update_const(mod - 1);
1120 if (!fill_q(g2, ct->left, -1))
1121 return false;
1123 break;
1125 case ctt_lod: {
1126 stmt_node *node;
1127 if (!dc)
1128 return false;
1129 node = dc->extract_stmt_node(ct->op, false);
1130 if (!node)
1131 return false;
1132 node->var = sa->create_tmp();
1133 node->op = ct->op;
1134 s->nested.push_back(node);
1135 h.update_coef(s->get_local(sa->vars[node->var]), mult);
1136 return true;
1138 default:
1139 assert(0);
1142 return true;
1145 bool guard_constructor::construct_guard(condition_tree *ct, F_And *f)
1147 switch (ct->type) {
1148 case ctt_invalid:
1149 return false;
1150 case ctt_ge: {
1151 GEQ_Handle g = f->add_GEQ();
1152 return fill_q(g, ct->left, 1);
1154 case ctt_eq: {
1155 EQ_Handle g = f->add_EQ();
1156 return fill_q(g, ct->left, 1);
1158 case ctt_or: {
1159 F_Or *o = f->add_or();
1160 if (!construct_guard(ct->left, o->add_and()))
1161 return false;
1162 return construct_guard(ct->right, o->add_and());
1164 case ctt_and: {
1165 if (!construct_guard(ct->left, f->add_and()))
1166 return false;
1167 return construct_guard(ct->right, f->add_and());
1169 default:
1170 assert(0);
1174 /* Replace each ctt_sym node in the tree that has a value associated
1175 * with it in the symtab_ann with this value.
1177 static condition_tree *substitute_values(condition_tree *ct, symtab_ann *sa)
1179 if (ct->type == ctt_sym && sa->vars.find(ct->var) != sa->vars.end()) {
1180 Param_Iterator *var = sa->vars[ct->var];
1181 if (var->value) {
1182 delete ct;
1183 return var->value->dup();
1186 if (ct->left)
1187 ct->left = substitute_values(ct->left, sa);
1188 if (ct->right)
1189 ct->right = substitute_values(ct->right, sa);
1190 return ct;
1193 bool guard_constructor::construct_guard(instruction *ins)
1195 condition_tree *ct = construct_condition_tree(ins, verbose);
1196 ct = substitute_values(ct, sa);
1197 ct->eliminate_minmax();
1198 bool ok = construct_guard(ct, s->f);
1199 delete ct;
1200 return ok;
1203 static void set_truth_value(suif_object *o, SRelation *sr,
1204 tree_if *ti, tree_node_list *tnl)
1206 if (tnl == ti->then_part()) {
1207 SRelation *s = (SRelation *)ti->peek_annote(k_if_annote);
1208 assert(s);
1209 SRelation *news = sr->Intersection(s);
1210 delete sr;
1211 sr = news;
1213 if (tnl == ti->else_part()) {
1214 SRelation *s = (SRelation *)ti->peek_annote(k_if_annote);
1215 assert(s);
1216 SRelation *news = sr->Difference(s);
1217 delete sr;
1218 sr = news;
1220 SRelation *s = (SRelation *)o->get_annote(k_if_annote);
1221 if (s) {
1222 SRelation *news = sr->Union(s);
1223 delete sr;
1224 delete s;
1225 sr = news;
1227 o->append_annote(k_if_annote, sr);
1230 /* Construct a guard from tnl and attach it to ti.
1231 * If allow_nested is set, then the domain_constructor is passed
1232 * to the guard_constructor, so that it can construct nested accesses.
1234 boolean domain_constructor::construct_guard(tree_if *ti, tree_node_list *tnl,
1235 bool allow_nested)
1237 tree_node_list_iter tnli(tnl);
1239 for (int i = 0; !tnli.is_empty(); ++i) {
1240 tree_node *tn = tnli.step();
1241 switch (tn->kind()) {
1242 case TREE_INSTR: {
1243 tree_instr *in = (tree_instr*)tn;
1244 switch (in->instr()->opcode()) {
1245 case io_btrue:
1246 case io_bfalse: {
1247 in_bj *bj = (in_bj *)in->instr();
1248 operand op = bj->src_op();
1249 SRelation *sr = NULL;
1250 switch (op.kind()) {
1251 case OPER_INSTR: {
1252 instruction * ins = op.instr();
1253 guard_constructor gc(sa, verbose,
1254 allow_nested ? this : NULL);
1255 bool ok = gc.construct_guard(ins);
1256 if (ok) {
1257 if (in->instr()->opcode() == io_bfalse)
1258 sr = new SRelation(*gc.s);
1259 else
1260 sr = gc.s->Complement();
1262 break;
1264 case OPER_SYM: {
1265 sym_node *v= op.symbol();
1266 SRelation *s = (SRelation *)v->peek_annote(k_if_annote);
1267 assert(s);
1268 if (in->instr()->opcode() == io_bfalse)
1269 sr = new SRelation(*s);
1270 else
1271 sr = s->Complement();
1272 break;
1274 default:
1275 assert(0);
1277 assert(tnl == ti->header());
1278 if (sr)
1279 ti->append_annote(k_if_annote, sr);
1280 return sr != NULL;
1282 case io_seq:
1283 case io_sl:
1284 case io_sle: {
1285 guard_constructor gc(sa, verbose, allow_nested ? this : NULL);
1286 boolean ok = gc.construct_guard(in->instr());
1287 assert(in->instr()->dst_op().kind() == OPER_SYM);
1288 sym_node* v = in->instr()->dst_op().symbol();
1289 if (ok)
1290 set_truth_value(v, new SRelation(*gc.s), ti, tnl);
1291 else
1292 return ok;
1293 break;
1295 case io_cpy: {
1296 assert(in->instr()->dst_op().kind() == OPER_SYM);
1297 sym_node* vd = in->instr()->dst_op().symbol();
1298 assert(in->instr()->src_op(0).kind() == OPER_SYM);
1299 sym_node* vs = in->instr()->src_op(0).symbol();
1300 SRelation *s = (SRelation *)vs->peek_annote(k_if_annote);
1301 assert(s);
1302 set_truth_value(vd, new SRelation(*s), ti, tnl);
1303 break;
1305 case io_mrk:
1306 break;
1307 default:
1308 if (verbose) {
1309 fprintf(stderr, "Unhandled guard:\n");
1310 in->instr()->print(stderr);
1312 return false;
1314 break;
1316 case TREE_IF: {
1317 tree_if *ti = (tree_if *) tn;
1318 bool ok = construct_guard(ti, ti->header(), allow_nested) &&
1319 construct_guard(ti, ti->then_part(), allow_nested) &&
1320 construct_guard(ti, ti->else_part(), allow_nested);
1321 if (!ok)
1322 return ok;
1323 break;
1325 default:
1326 return false;
1329 return true;
1332 /* Check if the bound computed by SUIF is ok.
1333 * First, if SUIF return NULL, then the bound is obviously not OK.
1334 * Second, if any of the variables involved is not an iterator
1335 * or a parameter, but a variable with a fixed value assigned, then
1336 * we need to substitute that value and so the bound computed
1337 * by SUIF is not OK.
1339 static bool valid_bound(symtab_ann *sa, named_lin_ineq *nlq)
1341 if (!nlq)
1342 return false;
1344 for (int i = 1; i < nlq->names().n(); ++i) {
1345 var_sym *v = nlq->names()[i].var();
1346 if (sa->vars.find(v) == sa->vars.end())
1347 continue;
1348 if (sa->vars[v]->value)
1349 return false;
1352 return true;
1355 /* If tnl contains a signle top level assignement, then
1356 * return the corresponding instruction. Otherwise, return NULL.
1358 static instruction *single_assignment(tree_node_list *tnl)
1360 tree_instr *in;
1361 tree_node_list_iter tnli(tnl);
1362 for (int i = 0; !tnli.is_empty(); ++i) {
1363 tree_node *tn = tnli.step();
1364 if (tn->kind() != TREE_INSTR)
1365 return NULL;
1366 in = (tree_instr*)tn;
1367 if (in->instr()->opcode() == io_mrk)
1368 continue;
1369 break;
1371 if (!tnli.is_empty())
1372 return NULL;
1374 switch (in->instr()->opcode()) {
1375 case io_ldc:
1376 case io_lod:
1377 case io_memcpy:
1378 case io_str:
1379 return in->instr();
1382 return NULL;
1385 static bool equal(operand op1, operand op2)
1387 if (op1.kind() != op2.kind())
1388 return false;
1389 switch (op1.kind()) {
1390 case OPER_INSTR: {
1391 if (op1.instr()->opcode() != op2.instr()->opcode())
1392 return false;
1393 if (op1.instr()->opcode() == io_ldc) {
1394 in_ldc *in1 = dynamic_cast<in_ldc *>(op1.instr());
1395 in_ldc *in2 = dynamic_cast<in_ldc *>(op2.instr());
1396 if (in1->value() != in2->value())
1397 return false;
1399 for (unsigned n = 0; n < op1.instr()->num_srcs(); n++) {
1400 if (!equal(op1.instr()->src_op(n), op2.instr()->src_op(n)))
1401 return false;
1403 break;
1405 case OPER_SYM:
1406 return op1.symbol() == op2.symbol();
1407 case OPER_NULL:
1408 return true;
1409 default:
1410 return false;
1412 return true;
1415 /* Add the data dependent conditions in c to all accesses in n.
1417 static void add_data_dependent_conditions(stmt_node *n, SRelation *c)
1419 if (n->is_access()) {
1420 stmt_access *a = static_cast<stmt_access *>(n);
1421 SRelation *map = c->Intersection(a->map);
1422 delete a->map;
1423 a->map = map;
1424 } else {
1425 stmt_call *call = static_cast<stmt_call *>(n);
1426 for (int i = 0; i < call->arg.size(); ++i)
1427 add_data_dependent_conditions(call->arg[i], c);
1431 /* Return the operand that identifies the write of the assignment instruction i.
1433 static operand write_op(instruction *i)
1435 switch (i->opcode()) {
1436 case io_ldc:
1437 case io_lod:
1438 return i->dst_op(0);
1439 case io_memcpy:
1440 case io_str:
1441 return i->src_op(0);
1443 assert(0);
1446 /* Return a stmt_node corresponding to the read performed
1447 * in the assignment instruction i.
1449 stmt_node *domain_constructor::read_stmt(instruction *i)
1451 switch (i->opcode()) {
1452 case io_ldc:
1453 case io_lod:
1454 return extract_stmt_node(i);
1455 case io_memcpy:
1456 case io_str: {
1457 operand r = i->src_op(1);
1458 return extract_stmt_node(r, false);
1461 assert(0);
1464 /* Return an "iterator" access, that accesses the constant "1"
1465 * when the conditions c1 hold and the constant "0" when the
1466 * conditions c0 hold. That is, assuming c0 is the complement
1467 * of c1, return an access that encodes the conditions c1.
1469 stmt_access *domain_constructor::data_dependent_test_cond(
1470 SRelation *c1, SRelation *c0)
1472 if (out.size() == 0)
1473 out.push_back(sa->create_tmp());
1474 sa->add_var(out[0]);
1476 Relation r(0,0);
1477 EQ_Handle g;
1479 SRelation *s1 = new SRelation(r, sa);
1480 s1->e = s1->add_exists();
1481 s1->f = s1->e->add_and();
1482 g = s1->f->add_EQ();
1483 g.update_const(1);
1484 g.update_coef(s1->get_local(sa->vars[out[0]]), -1);
1486 SRelation *t1 = s1->Intersection(c1);
1487 delete s1;
1489 SRelation *s0 = new SRelation(r, sa);
1490 s0->e = s0->add_exists();
1491 s0->f = s0->e->add_and();
1492 g = s0->f->add_EQ();
1493 g.update_const(0);
1494 g.update_coef(s0->get_local(sa->vars[out[0]]), -1);
1496 SRelation *t0 = s0->Intersection(c0);
1497 delete s0;
1499 SRelation *c = t0->Union(t1);
1500 delete t0;
1501 delete t1;
1503 return new stmt_access(false, c, NULL, 1);
1506 /* Check if the if "ti" represents a data dependent assignment
1507 * and if so, attach the corresponding data dependent statement
1508 * to this node.
1510 * A data dependent assignment is an assignment of the form
1512 * if (data dependent conditions)
1513 * a = f(...);
1514 * else
1515 * a = g(...);
1517 * The data dependent statement constructed is of the form
1519 * a = #test(data dependent conditions, f(...), g(...))
1521 * where all the access relations in f have been updated to
1522 * include the data dependent conditions and all those in g
1523 * have been updated to include the negation of these conditions.
1524 * Note that this means that the access relations may only
1525 * select a subset of the iteration domains.
1526 * The data dependent conditions are therefore also explicitly
1527 * encoded in the first argument.
1529 * We first check that the then and else branches each contain
1530 * a single assignment.
1531 * Both assignments should assign to the same scalar or array element.
1532 * We then see if we can analyze the conditions, allowing for nested accesses,
1533 * and if so construct the #test statement.
1535 bool domain_constructor::is_data_dependent_assignment(tree_if *ti)
1537 instruction *in_then, *in_else;
1539 in_then = single_assignment(ti->then_part());
1540 in_else = single_assignment(ti->else_part());
1542 if (!in_then || !in_else)
1543 return false;
1545 if (in_then->num_dsts() != in_else->num_dsts())
1546 return false;
1548 operand then_write = write_op(in_then);
1549 operand else_write = write_op(in_else);
1551 if (!equal(then_write, else_write))
1552 return false;
1554 bool ok = construct_guard(ti, ti->header(), true);
1555 if (!ok)
1556 return false;
1558 SRelation *sr = (SRelation *)ti->peek_annote(k_if_annote);
1559 assert(sr);
1561 stmt_node *out;
1562 out = extract_stmt_node(then_write, true, in_then);
1563 if (!out)
1564 return false;
1566 stmt_node *node_then = read_stmt(in_then);
1567 if (!node_then) {
1568 delete out;
1569 return false;
1571 stmt_node *node_else = read_stmt(in_else);
1572 if (!node_else) {
1573 delete out;
1574 delete node_then;
1575 return false;
1578 add_data_dependent_conditions(node_then, sr);
1580 SRelation *c = sr->Complement();
1581 add_data_dependent_conditions(node_else, c);
1582 stmt_access *cond = data_dependent_test_cond(sr, c);
1583 delete c;
1585 stmt_call *test = new stmt_call("#test");
1586 test->arg.push_back(cond);
1587 test->arg.push_back(node_then);
1588 test->arg.push_back(node_else);
1590 stmt *s = new stmt;
1591 s->tree = test;
1592 s = add_access(s, out);
1594 ti->append_annote(k_stmt, s);
1596 return true;
1599 /* Move up to old_scope and remove any assignments that
1600 * have been performed inside the current scope (if it
1601 * is different from old_scope).
1603 void domain_constructor::leave_scope(tree_node *old_scope)
1605 if (old_scope == scope)
1606 return;
1607 annote_list_iter anli(scope->annotes());
1608 while (!anli.is_empty()) {
1609 annote *an = anli.step();
1610 if (an->name() != k_set_in_scope)
1611 continue;
1612 var_sym *array = (var_sym *)an->data();
1613 if (sa->vars[array]->value)
1614 delete sa->vars[array]->value;
1615 sa->vars[array]->value = NULL;
1617 scope = old_scope;
1620 boolean domain_constructor::scan(tree_node * tn)
1622 boolean ok = true;
1623 stmt *stmt = NULL;
1624 tree_node *old_scope = scope;
1626 switch (tn->kind()) {
1627 case TREE_INSTR: {
1628 tree_instr *in = (tree_instr*)tn;
1629 switch (in->instr()->opcode()) {
1630 case io_memcpy:
1631 case io_cpy:
1632 case io_str:
1633 case io_lod:
1634 case io_cvt:
1635 case io_ldc:
1636 case io_add:
1637 case io_sub:
1638 case io_mul:
1639 case io_div:
1640 case io_rem:
1641 case io_cal:
1642 root = in->instr();
1643 stmt = extract_stmt(in);
1644 if (stmt)
1645 root->append_annote(k_stmt, stmt);
1646 ok = stmt != NULL;
1647 break;
1648 case io_mrk:
1649 break;
1650 default:
1651 if (verbose) {
1652 fprintf(stderr, "Unhandled instruction:\n");
1653 in->instr()->print(stderr);
1655 ok = false;
1656 break;
1658 break;
1660 case TREE_IF: {
1661 scope = tn;
1662 tree_if *ti = (tree_if *) tn;
1663 boolean guard_ok;
1664 guard_ok = construct_guard(ti, ti->header(), NULL);
1665 if (guard_ok)
1666 ok = scan(ti->then_part()) && scan(ti->else_part());
1667 else
1668 ok = is_data_dependent_assignment(ti);
1669 break;
1671 case TREE_FOR: {
1672 scope = tn;
1673 dep_for_annote * df =
1674 (dep_for_annote *)tn->peek_annote(k_dep_for_annote);
1675 named_lin_ineq *lb, *ub;
1676 tree_for * tf = df->my_for;
1677 sa->add_var(tf->index());
1678 sa->vars[tf->index()]->iterator = true;
1679 sa->vars[tf->index()]->valid_for_read = true;
1680 delete sa->vars[tf->index()]->value;
1681 sa->vars[tf->index()]->value = NULL;
1682 immed idx(tf->index());
1683 lb = named_lin_ineq::mk_named_lin_ineq(*df->lb, idx, TRUE);
1684 ub = named_lin_ineq::mk_named_lin_ineq(*df->ub, idx, FALSE);
1685 sa->add_var(lb);
1686 sa->add_var(ub);
1687 ok = valid_bound(sa, lb) && valid_bound(sa, ub);
1688 if (lb)
1689 delete lb;
1690 if (ub)
1691 delete ub;
1692 if (!ok) {
1693 instruction *lower = new in_rrr(io_sle, tf->index()->type(),
1694 operand(), tf->lb_op().clone(), operand(tf->index()));
1695 guard_constructor gc_lower(sa, verbose, NULL);
1696 ok = gc_lower.construct_guard(lower);
1697 delete lower;
1698 if (!ok)
1699 break;
1701 instruction *upper = new in_rrr(io_sle, tf->index()->type(),
1702 operand(), operand(tf->index()), tf->ub_op().clone());
1703 guard_constructor gc_upper(sa, verbose, NULL);
1704 ok = gc_upper.construct_guard(upper);
1705 delete upper;
1706 if (!ok)
1707 break;
1709 Relation I = Intersection(*gc_lower.s, *gc_upper.s);
1710 tn->append_annote(k_for_annote,
1711 new for_ann(new SRelation(I, sa), tf->index(), tf->body()));
1713 ok = scan(tf->body());
1714 sa->vars[tf->index()]->iterator = false;
1715 if (sa->vars[tf->index()]->assigned)
1716 sa->vars[tf->index()]->valid_for_read = false;
1717 break;
1719 case TREE_LOOP: {
1720 scope = tn;
1721 /* We only accept infinite loops */
1722 tree_loop *tl = static_cast<tree_loop *>(tn);
1723 tree_node_list *tnl = tl->test();
1724 tree_node_list_iter tnli(tnl);
1725 bool infinite_loop = false;
1727 /* Simple test for infinite loop:
1728 * a loop whose test jumps right back to the top of the loop.
1730 while (!tnli.is_empty()) {
1731 tree_node *t = tnli.step();
1732 if (t->kind() != TREE_INSTR)
1733 break;
1734 tree_instr *in = static_cast<tree_instr*>(t);
1735 if (in->instr()->opcode() == io_mrk)
1736 continue;
1737 if (in->instr()->opcode() != io_jmp)
1738 break;
1739 in_bj *bj = static_cast<in_bj *>(in->instr());
1740 if (bj->target() != tl->toplab())
1741 break;
1742 infinite_loop = true;
1743 break;
1745 ok = infinite_loop && scan(tl->body());
1746 break;
1748 default:
1749 unsigned n = tn->num_child_lists();
1750 for (unsigned i = 0; ok && i < n; ++i)
1751 ok = scan(tn->child_list_num(i));
1753 leave_scope(old_scope);
1755 return ok;
1758 /* If the tree_node_list consists entirely of zero or more marks and
1759 * exactly one test, return the test. Otherwise return NULL.
1761 static tree_instr *if_test(tree_node_list *tnl)
1763 tree_instr *test = NULL;
1764 tree_node_list_iter tnli(tnl);
1765 for (int i = 0; !tnli.is_empty(); ++i) {
1766 tree_node *tn = tnli.step();
1767 switch (tn->kind()) {
1768 case TREE_INSTR: {
1769 tree_instr *in = (tree_instr*)tn;
1770 switch (in->instr()->opcode()) {
1771 case io_btrue:
1772 case io_bfalse:
1773 if (!test)
1774 test = in;
1775 else
1776 return NULL;
1777 break;
1778 case io_mrk:
1779 break;
1780 default:
1781 return NULL;
1783 break;
1785 default:
1786 return NULL;
1789 return test;
1792 /* If the tree_node_list consists out of an increment followed by a test,
1793 * possibly interspersed by marks, then return true and put a pointer to
1794 * the increment and the test in inc and test.
1795 * Otherwise return false.
1797 static bool loop_extract_increment_and_test(tree_node_list *tnl,
1798 tree_instr **inc, tree_instr **test)
1800 *inc = NULL;
1801 *test = NULL;
1802 tree_node_list_iter tnli(tnl);
1803 for (int i = 0; !tnli.is_empty(); ++i) {
1804 tree_node *tn = tnli.step();
1805 switch (tn->kind()) {
1806 case TREE_INSTR: {
1807 tree_instr *in = (tree_instr*)tn;
1808 switch (in->instr()->opcode()) {
1809 case io_add:
1810 if (!*inc)
1811 *inc = in;
1812 else
1813 return false;
1814 break;
1815 case io_btrue:
1816 case io_bfalse:
1817 if (*inc && !*test)
1818 *test = in;
1819 else
1820 return false;
1821 break;
1822 case io_mrk:
1823 break;
1824 default:
1825 return false;
1827 break;
1829 default:
1830 return false;
1833 return true;
1836 /* Return true if instruction "i" contains an increment on
1837 * the variable "iterator".
1839 static bool is_increment_on(instruction *i, var_sym *iterator)
1841 if (i->opcode() != io_add)
1842 return false;
1843 if (!i->dst_op(0).is_symbol())
1844 return false;
1845 if (i->dst_op(0).symbol() != iterator)
1846 return false;
1847 if (!i->src_op(0).is_symbol())
1848 return false;
1849 if (i->src_op(0).symbol() != iterator)
1850 return false;
1851 if (!i->src_op(1).is_instr())
1852 return false;
1853 if (i->src_op(1).instr()->opcode() != io_ldc)
1854 return false;
1855 in_ldc *ins = dynamic_cast<in_ldc *>(i->src_op(1).instr());
1856 if (!ins->value().is_integer())
1857 return false;
1858 if (ins->value().integer() != 1)
1859 return false;
1860 return true;
1863 /* Check whether the pair of successive tree nodes t1 and t2 represent
1864 * a for loop that was dismantled by snoot.
1865 * If so, return true and return the body of that for loop in *body.
1867 * snoot breaks up a for loop of the form
1869 * for (init; test; update) {
1870 * body
1873 * as
1875 * init;
1876 * if (test) {
1877 * do {
1878 * body;
1879 * } while (update, test);
1882 * We check that the first instruction "init" modifies some symbol ("iterator")
1883 * and that we can recognize "init <= iterator" as a lower bound for a for loop.
1885 * Then we check that the second instruction is an IF without else part
1886 * and with a nested LOOP, that the if and the test have the same test,
1887 * that it involves the iterator and that it can be recognized as an
1888 * upper bound of a for loop.
1889 * Finally, the update should increment "iterator".
1891 * If all these conditions are satisfied, we return true and attach
1892 * a for_ann to the first instruction, containing the body of the loop,
1893 * the loop iterator and the lower and upper bounds.
1895 bool domain_constructor::is_broken_up_loop(tree_node *t1, tree_node *t2,
1896 tree_node_list **body, var_sym **iterator)
1898 if (t1->kind() != TREE_INSTR)
1899 return false;
1900 if (t2->kind() != TREE_IF)
1901 return false;
1902 tree_if *ti = (tree_if *) t2;
1903 if (ti->else_part()->count())
1904 return false;
1905 tree_node_list *if_body = ti->then_part();
1906 if (if_body->count() != 1)
1907 return false;
1908 tree_node *tn = if_body->head()->contents;
1909 if (tn->kind() != TREE_LOOP)
1910 return false;
1911 tree_loop *tl = (tree_loop *) tn;
1913 tree_instr *init = (tree_instr *)t1;
1915 if (!init->instr()->dst_op(0).is_symbol())
1916 return false;
1918 *iterator = init->instr()->dst_op(0).symbol();
1920 tree_instr *ti_test = if_test(ti->header());
1921 if (!ti_test)
1922 return false;
1924 tree_instr *tl_inc;
1925 tree_instr *tl_test;
1926 if (!loop_extract_increment_and_test(tl->test(), &tl_inc, &tl_test))
1927 return false;
1929 if (ti_test->instr()->opcode() != io_bfalse)
1930 return false;
1932 if (tl_test->instr()->opcode() != io_btrue)
1933 return false;
1935 if (!equal(ti_test->instr()->src_op(0), tl_test->instr()->src_op(0)))
1936 return false;
1938 if (!is_increment_on(tl_inc->instr(), *iterator))
1939 return false;
1941 if (ti_test->instr()->src_op(0).kind() != OPER_INSTR)
1942 return false;
1944 instruction *in = ti_test->instr()->src_op(0).instr();
1945 if (in->opcode() != io_sl && in->opcode() != io_sle)
1946 return false;
1948 if (!in->src_op(0).is_symbol())
1949 return false;
1950 if (in->src_op(0).symbol() != *iterator)
1951 return false;
1953 sa->add_var(*iterator);
1954 sa->vars[*iterator]->iterator = true;
1955 delete sa->vars[*iterator]->value;
1956 sa->vars[*iterator]->value = NULL;
1957 sa->vars[*iterator]->valid_for_read = true;
1959 bool ok;
1960 guard_constructor gc(sa, verbose, NULL);
1961 ok = gc.construct_guard(in);
1962 if (!ok)
1963 return false;
1965 instruction *lower = new in_rrr(io_sle, (*iterator)->type(), operand(),
1966 init->instr()->clone(), operand(*iterator));
1968 guard_constructor gc_lower(sa, verbose, NULL);
1969 ok = gc_lower.construct_guard(lower);
1970 delete lower;
1971 if (!ok)
1972 return false;
1974 Relation I = Intersection(*gc.s, *gc_lower.s);
1975 *body = tl->body();
1976 t1->append_annote(k_for_annote,
1977 new for_ann(new SRelation(I, sa), *iterator, *body));
1979 return true;
1982 boolean domain_constructor::scan(tree_node_list * tnl)
1984 tree_node_list_e *start = NULL;
1986 tree_node_list_iter tnli(tnl);
1987 for (int i = 0; !tnli.is_empty(); ++i) {
1988 tree_node *t = tnli.step();
1989 tree_node_list *body = NULL;
1990 var_sym *iterator = NULL;
1991 bool ok;
1992 if (!tnli.is_empty() &&
1993 is_broken_up_loop(t, tnli.peek(), &body, &iterator)) {
1994 ok = scan(body);
1995 sa->vars[iterator]->iterator = false;
1996 if (sa->vars[iterator]->assigned)
1997 sa->vars[iterator]->valid_for_read = false;
1998 tnli.step();
1999 } else
2000 ok = scan(t);
2001 if (ok) {
2002 if (!start)
2003 start = t->list_e();
2004 } else if (start) {
2005 tree_node *root;
2007 if (start->next() == t->list_e())
2008 root = start->contents;
2009 else {
2010 block_symtab *st = new block_symtab("static root");
2011 tnl->scope()->add_child(st);
2012 tree_node_list *tl = new tree_node_list;
2013 tree_block *tb = new tree_block(tl, st);
2014 tnl->insert_before(tb, start);
2015 tb->proc()->block()->number_instrs();
2017 tree_node_list_e *next = start->next();
2018 while (start != t->list_e()) {
2019 tnl->remove(start);
2020 tl->append(start);
2021 start = next;
2022 next = start->next();
2024 root = tb;
2026 if (!(root->kind() == TREE_INSTR &&
2027 ((tree_instr*)root)->instr()->opcode() == io_mrk))
2028 root->append_annote(k_static_root, new immed_list());
2030 start = NULL;
2034 return start == tnl->head();
2037 void domain_constructor::scan(context_info *ctx)
2039 sa = new symtab_ann;
2040 sa->symtab = new global_symtab("statement iterators");
2041 level = 0;
2043 std::map<var_sym *, Param_Iterator *>::iterator gi;
2044 for (gi = ctx->sa->vars.begin(); gi != ctx->sa->vars.end(); ++gi)
2045 sa->vars[(*gi).first] = (*gi).second;
2047 tp->append_annote(k_domain_symtab, sa);
2048 scan(tp->body());
2051 void construct_domains(tree_proc * tp, int verbose, int oldstyle, context_info *ctx)
2053 domain_constructor dc(tp, verbose, oldstyle);
2054 dc.scan(ctx);
2055 dc.construct();
2058 static void free_stmt(void *data)
2060 stmt *s = (stmt *)data;
2061 delete s;
2064 static void
2065 free_domain_ann(void *data)
2067 domain_ann *da = (domain_ann *) data;
2068 delete da->domain;
2069 delete da;
2072 static void
2073 free_symtab(void *data)
2075 symtab_ann *sa = (symtab_ann *) data;
2076 delete sa->symtab;
2077 delete sa;
2080 static void free_srelation(void *data)
2082 SRelation *sr = (SRelation *) data;
2083 delete sr;
2086 static void free_for_ann(void *data)
2088 delete (for_ann *) data;
2091 void
2092 init(int &argc, char *argv[])
2094 ANNOTE(k_static_root, "pers_static_root", FALSE);
2095 STRUCT_ANNOTE(k_stmt, "pers_stmt", FALSE,
2096 NULL, NULL, free_stmt, NULL);
2097 STRUCT_ANNOTE(k_iteration_domain, "pers_iteration_domain", FALSE,
2098 NULL, NULL, free_domain_ann, NULL);
2099 STRUCT_ANNOTE(k_domain_symtab, "pers_domain_symtab", FALSE,
2100 NULL, NULL, free_symtab, NULL);
2101 STRUCT_ANNOTE(k_if_annote, "pers_if_annote", FALSE,
2102 NULL, NULL, free_srelation, NULL);
2103 STRUCT_ANNOTE(k_for_annote, "pers_for_annote", FALSE,
2104 NULL, NULL, free_for_ann, NULL);
2105 STRUCT_ANNOTE(k_array_bounds, "pers_array_bounds", FALSE,
2106 NULL, NULL, free_srelation, NULL);
2107 STRUCT_ANNOTE(k_set_in_scope, "pers_set_in_scope", FALSE,
2108 NULL, NULL, NULL, NULL);