6 const char * k_static_root
;
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
)
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
);
33 vars
[tmp
]->temp
= true;
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
);
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
113 * These are updated to
115 * m d - f + m - 1 >= 0
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()) {
128 in_ldc
*ins
= dynamic_cast<in_ldc
*>(in
);
129 f
*= ins
->value().integer();
134 extract_messy_index(map
, h
, in
->src_op(0), f
);
135 extract_messy_index(map
, h
, in
->src_op(1), f
);
138 extract_messy_index(map
, h
, in
->src_op(0), f
);
139 extract_messy_index(map
, h
, in
->src_op(1), -f
);
142 extract_messy_index(map
, h
, in
->src_op(0), -f
);
146 operand r
= in
->src_op(0);
147 node
= extract_stmt_node(r
, false);
149 node
->var
= sa
->create_tmp();
151 map
->nested
.push_back(node
);
152 h
.update_coef(map
->get_local(sa
->vars
[node
->var
]), f
);
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
);
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
);
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();
183 Variable_ID q
= map
->e
->declare();
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);
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
215 static bool data_dependent(access_vector
*av
, symtab_ann
*sa
)
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
))
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
)
240 extract_messy_index(map
, h
, op
.instr(), f
);
244 assert(op
.is_symbol());
245 assert(!op
.symbol()->type()->is_ptr());
247 if (data_dependent(op
.symbol(), sa
)) {
249 node
= extract_stmt_node(op
, false);
251 node
->var
= sa
->create_tmp();
253 map
->nested
.push_back(node
);
254 h
.update_coef(map
->get_local(sa
->vars
[node
->var
]), f
);
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
)
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);
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());
290 switch (ina
->base_op().instr()->opcode()) {
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();
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();
309 named_lin_ineq
*nlq
= new named_lin_ineq();
310 SRelation
*map
= new SRelation(sa
, nlq
);
311 array_info_iter
iter(di
->ai
);
313 for(i
= 0; !iter
.is_empty(); ++i
) {
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
;
322 m
= extract_messy_index(ina
->index(i
), out
[i
]);
323 map
= map
->Intersection(m
);
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
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
);
346 map
->intersect(named_lin_ineq::mk_named_lin_ineq(*av
, out
[i
],
348 map
->intersect(named_lin_ineq::mk_named_lin_ineq(*av
, out
[i
],
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
);
363 return create_access(di
, write
);
366 /* Is it ok to write to (write = true) or read from (write = false)
368 * It is not ok to write to a variable that is currently being used
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
)
380 if (!write
&& !var
->iterator
&& !var
->valid_for_read
)
385 /* Check whether ct contains any invalid nodes or data dependent
387 * If so, then this condition tree shouldn't be considered as
390 static bool invalid_or_data_dependent(condition_tree
*ct
, symtab_ann
*sa
)
400 return invalid_or_data_dependent(ct
->left
, sa
) ||
401 invalid_or_data_dependent(ct
->right
, sa
);
403 return invalid_or_data_dependent(ct
->right
, sa
);
407 return invalid_or_data_dependent(ct
->left
, sa
);
409 return data_dependent(ct
->var
, sa
);
414 /* Check whether ct contains any invalid nodes.
416 static bool invalid(condition_tree
*ct
, symtab_ann
*sa
)
429 return invalid(ct
->left
, sa
) ||
430 invalid(ct
->right
, sa
);
432 return invalid(ct
->right
, sa
);
437 return invalid(ct
->left
, sa
);
442 stmt_node
*domain_constructor::extract_stmt_node(operand
&op
, bool write
,
446 return extract_stmt_node(op
.instr());
448 if (!op
.is_symbol()) {
453 if (op
.symbol()->type()->is_ptr())
455 named_lin_ineq
*a
= new named_lin_ineq();
456 var_sym
*array
= op
.symbol();
458 bool iterator_access
= false;
459 if (sa
->vars
.find(array
) != sa
->vars
.end()) {
460 if (!is_access_ok(sa
, array
, write
)) {
462 parent
->print(stderr
);
464 assert(is_access_ok(sa
, array
, write
));
465 iterator_access
= !sa
->vars
[array
]->assigned
||
466 sa
->vars
[array
]->iterator
;
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
;
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 */
487 out
.push_back(sa
->create_tmp());
488 a
->ineqs().init(2,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;
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
);
511 s
->out
.push_back(acc
);
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();
525 if (i
->opcode() == io_str
|| i
->opcode() == io_memcpy
) {
526 out
= extract_stmt_node(i
->src_op(0).instr());
529 operand r
= i
->src_op(1);
530 node
= extract_stmt_node(r
, false);
532 node
= extract_stmt_node(i
);
544 s
= add_access(s
, out
);
548 for (unsigned n
= 0; n
< i
->num_dsts(); n
++) {
549 operand r
= i
->dst_op(n
);
552 stmt_node
*dst
= extract_stmt_node(r
, true, i
);
553 s
= add_access(s
, dst
);
561 static char *immed2str(immed im
)
563 std::ostringstream strm
;
567 strm
<< im
.integer();
573 fprintf(stderr
, "unsupported immed type: %d\n", im
.kind());
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());
589 if (i
->opcode() == io_str
|| i
->opcode() == io_cpy
)
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
)
597 if (i
->opcode() == io_sub
)
599 if (i
->opcode() == io_mul
)
601 if (i
->opcode() == io_div
)
603 if (i
->opcode() == io_rem
)
605 if (i
->opcode() == io_neg
)
607 if (i
->opcode() == io_sl
)
609 fprintf(stderr
, "unrecognized instruction\n");
614 stmt_node
*domain_constructor::extract_stmt_node(instruction
*i
)
618 node
= check_access(i
, false);
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
);
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 */
643 node
= extract_stmt_node(r
, false);
648 call
->arg
.push_back(node
);
654 stmt_node
*domain_constructor::extract_stmt_node_cal(in_cal
*cal
)
656 const char *name
= instr_name(cal
);
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
) {
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);
685 call
->arg
.push_back(node
);
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
);
701 call
->arg
.push_back(node
);
705 in_ldc
*ldc
= dynamic_cast<in_ldc
*>(op
.instr());
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
);
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
);
725 prefix
[plevel
] = prefix_value
;
727 if (!iterator
&& level
< its
.size() && its
[level
]->parent() == sa
->symtab
)
730 iterator
= sa
->symtab
->new_unique_var(type_signed
);
731 if (level
>= its
.size())
732 its
.push_back(iterator
);
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
)
742 c
= fa
->bounds
->Intersection(oldc
);
744 set_prefix_and_iterator(-1, fa
->iterator
);
756 /* Create 1D set with given lower and upper bounds.
758 static SRelation
*set_from_bounds(int lb
, int ub
, symtab_ann
*sa
)
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);
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
)
782 *i
= strtol(im
.string(), NULL
, 0);
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();
803 if (ims
->count() != 4)
805 if ((*ims
)[1].kind() != im_symbol
)
807 sym
= (*ims
)[1].symbol();
808 if (sym
->kind() != SYM_VAR
)
810 if (immed_to_int((*ims
)[2], &lb
))
812 if (immed_to_int((*ims
)[3], &ub
))
814 sym
->append_annote(k_array_bounds
, set_from_bounds(lb
, ub
, sa
));
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
)
832 immed_list
*ims
= an
->immeds();
833 if (!(*ims
)[0].is_string())
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
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
,
849 stmt
*s
= (stmt
*)obj
->peek_annote(k_stmt
);
853 SRelation
*o
= reorder(c
);
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
);
862 domain_constructor::construct(tree_node
* tn
)
864 switch (tn
->kind()) {
866 for_ann
*fa
= (for_ann
*)tn
->peek_annote(k_for_annote
);
868 construct_broken_up_loop(fa
);
871 tree_instr
*in
= (tree_instr
*)tn
;
872 switch (in
->instr()->opcode()) {
874 check_pragmas(in
->instr());
891 add_iteration_domain(root
, root
);
896 for_ann
*fa
= (for_ann
*)tn
->peek_annote(k_for_annote
);
898 construct_broken_up_loop(fa
);
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());
913 construct(tf
->body());
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
]);
931 construct(tl
->body());
940 tree_if
* ti
= (tree_if
*)tn
;
941 SRelation
* oldc
= c
;
943 if (tn
->peek_annote(k_stmt
)) {
944 add_iteration_domain(tn
, NULL
);
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.
954 c
= s
->Intersection(oldc
);
956 construct(ti
->then_part());
960 if (ti
->else_part()->is_empty()) {
965 c
= oldc
->Difference(s
);
967 construct(ti
->else_part());
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
);
992 c
->fix(its
[level
], i
);
1008 void domain_constructor::visit(tree_node
*t
)
1010 if (!t
->peek_annote(k_static_root
))
1013 c
= new SRelation(sa
);
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
)
1034 h
.update_const(mult
* ct
->val
);
1037 if (!fill_q(h
, ct
->left
, mult
))
1039 if (!fill_q(h
, ct
->right
, mult
))
1043 if (!fill_q(h
, ct
->left
, mult
))
1045 if (!fill_q(h
, ct
->right
, -mult
))
1049 sa
->add_var(ct
->var
);
1050 Param_Iterator
*var
= sa
->vars
[ct
->var
];
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
);
1060 operand
op(ct
->var
);
1061 node
= dc
->extract_stmt_node(op
, false);
1064 node
->var
= sa
->create_tmp();
1066 s
->nested
.push_back(node
);
1067 h
.update_coef(s
->get_local(sa
->vars
[node
->var
]), mult
);
1071 assert(ct
->left
->type
== ctt_cst
);
1072 return fill_q(h
, ct
->right
, mult
* ct
->left
->val
);
1074 if (!fill_q(h
, ct
->left
, -mult
))
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
);
1086 GEQ_Handle g1
= s
->f
->add_GEQ();
1087 g1
.update_coef(r
, 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))
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
);
1111 GEQ_Handle g1
= s
->f
->add_GEQ();
1112 g1
.update_coef(q
, -mod
);
1113 if (!fill_q(g1
, ct
->left
, 1))
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))
1129 node
= dc
->extract_stmt_node(ct
->op
, false);
1132 node
->var
= sa
->create_tmp();
1134 s
->nested
.push_back(node
);
1135 h
.update_coef(s
->get_local(sa
->vars
[node
->var
]), mult
);
1145 bool guard_constructor::construct_guard(condition_tree
*ct
, F_And
*f
)
1151 GEQ_Handle g
= f
->add_GEQ();
1152 return fill_q(g
, ct
->left
, 1);
1155 EQ_Handle g
= f
->add_EQ();
1156 return fill_q(g
, ct
->left
, 1);
1159 F_Or
*o
= f
->add_or();
1160 if (!construct_guard(ct
->left
, o
->add_and()))
1162 return construct_guard(ct
->right
, o
->add_and());
1165 if (!construct_guard(ct
->left
, f
->add_and()))
1167 return construct_guard(ct
->right
, f
->add_and());
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
];
1183 return var
->value
->dup();
1187 ct
->left
= substitute_values(ct
->left
, sa
);
1189 ct
->right
= substitute_values(ct
->right
, sa
);
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
);
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
);
1209 SRelation
*news
= sr
->Intersection(s
);
1213 if (tnl
== ti
->else_part()) {
1214 SRelation
*s
= (SRelation
*)ti
->peek_annote(k_if_annote
);
1216 SRelation
*news
= sr
->Difference(s
);
1220 SRelation
*s
= (SRelation
*)o
->get_annote(k_if_annote
);
1222 SRelation
*news
= sr
->Union(s
);
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
,
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()) {
1243 tree_instr
*in
= (tree_instr
*)tn
;
1244 switch (in
->instr()->opcode()) {
1247 in_bj
*bj
= (in_bj
*)in
->instr();
1248 operand op
= bj
->src_op();
1249 SRelation
*sr
= NULL
;
1250 switch (op
.kind()) {
1252 instruction
* ins
= op
.instr();
1253 guard_constructor
gc(sa
, verbose
,
1254 allow_nested
? this : NULL
);
1255 bool ok
= gc
.construct_guard(ins
);
1257 if (in
->instr()->opcode() == io_bfalse
)
1258 sr
= new SRelation(*gc
.s
);
1260 sr
= gc
.s
->Complement();
1265 sym_node
*v
= op
.symbol();
1266 SRelation
*s
= (SRelation
*)v
->peek_annote(k_if_annote
);
1268 if (in
->instr()->opcode() == io_bfalse
)
1269 sr
= new SRelation(*s
);
1271 sr
= s
->Complement();
1277 assert(tnl
== ti
->header());
1279 ti
->append_annote(k_if_annote
, sr
);
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();
1290 set_truth_value(v
, new SRelation(*gc
.s
), ti
, tnl
);
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
);
1302 set_truth_value(vd
, new SRelation(*s
), ti
, tnl
);
1309 fprintf(stderr
, "Unhandled guard:\n");
1310 in
->instr()->print(stderr
);
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
);
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
)
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())
1348 if (sa
->vars
[v
]->value
)
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
)
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
)
1366 in
= (tree_instr
*)tn
;
1367 if (in
->instr()->opcode() == io_mrk
)
1371 if (!tnli
.is_empty())
1374 switch (in
->instr()->opcode()) {
1385 static bool equal(operand op1
, operand op2
)
1387 if (op1
.kind() != op2
.kind())
1389 switch (op1
.kind()) {
1391 if (op1
.instr()->opcode() != op2
.instr()->opcode())
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())
1399 for (unsigned n
= 0; n
< op1
.instr()->num_srcs(); n
++) {
1400 if (!equal(op1
.instr()->src_op(n
), op2
.instr()->src_op(n
)))
1406 return op1
.symbol() == op2
.symbol();
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
);
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()) {
1438 return i
->dst_op(0);
1441 return i
->src_op(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()) {
1454 return extract_stmt_node(i
);
1457 operand r
= i
->src_op(1);
1458 return extract_stmt_node(r
, false);
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]);
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();
1484 g
.update_coef(s1
->get_local(sa
->vars
[out
[0]]), -1);
1486 SRelation
*t1
= s1
->Intersection(c1
);
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();
1494 g
.update_coef(s0
->get_local(sa
->vars
[out
[0]]), -1);
1496 SRelation
*t0
= s0
->Intersection(c0
);
1499 SRelation
*c
= t0
->Union(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
1510 * A data dependent assignment is an assignment of the form
1512 * if (data dependent conditions)
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
)
1545 if (in_then
->num_dsts() != in_else
->num_dsts())
1548 operand then_write
= write_op(in_then
);
1549 operand else_write
= write_op(in_else
);
1551 if (!equal(then_write
, else_write
))
1554 bool ok
= construct_guard(ti
, ti
->header(), true);
1558 SRelation
*sr
= (SRelation
*)ti
->peek_annote(k_if_annote
);
1562 out
= extract_stmt_node(then_write
, true, in_then
);
1566 stmt_node
*node_then
= read_stmt(in_then
);
1571 stmt_node
*node_else
= read_stmt(in_else
);
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
);
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
);
1592 s
= add_access(s
, out
);
1594 ti
->append_annote(k_stmt
, s
);
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
)
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
)
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
;
1620 boolean
domain_constructor::scan(tree_node
* tn
)
1624 tree_node
*old_scope
= scope
;
1626 switch (tn
->kind()) {
1628 tree_instr
*in
= (tree_instr
*)tn
;
1629 switch (in
->instr()->opcode()) {
1643 stmt
= extract_stmt(in
);
1645 root
->append_annote(k_stmt
, stmt
);
1652 fprintf(stderr
, "Unhandled instruction:\n");
1653 in
->instr()->print(stderr
);
1662 tree_if
*ti
= (tree_if
*) tn
;
1664 guard_ok
= construct_guard(ti
, ti
->header(), NULL
);
1666 ok
= scan(ti
->then_part()) && scan(ti
->else_part());
1668 ok
= is_data_dependent_assignment(ti
);
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
);
1687 ok
= valid_bound(sa
, lb
) && valid_bound(sa
, ub
);
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
);
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
);
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;
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
)
1734 tree_instr
*in
= static_cast<tree_instr
*>(t
);
1735 if (in
->instr()->opcode() == io_mrk
)
1737 if (in
->instr()->opcode() != io_jmp
)
1739 in_bj
*bj
= static_cast<in_bj
*>(in
->instr());
1740 if (bj
->target() != tl
->toplab())
1742 infinite_loop
= true;
1745 ok
= infinite_loop
&& scan(tl
->body());
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
);
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()) {
1769 tree_instr
*in
= (tree_instr
*)tn
;
1770 switch (in
->instr()->opcode()) {
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
)
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()) {
1807 tree_instr
*in
= (tree_instr
*)tn
;
1808 switch (in
->instr()->opcode()) {
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
)
1843 if (!i
->dst_op(0).is_symbol())
1845 if (i
->dst_op(0).symbol() != iterator
)
1847 if (!i
->src_op(0).is_symbol())
1849 if (i
->src_op(0).symbol() != iterator
)
1851 if (!i
->src_op(1).is_instr())
1853 if (i
->src_op(1).instr()->opcode() != io_ldc
)
1855 in_ldc
*ins
= dynamic_cast<in_ldc
*>(i
->src_op(1).instr());
1856 if (!ins
->value().is_integer())
1858 if (ins
->value().integer() != 1)
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) {
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
)
1900 if (t2
->kind() != TREE_IF
)
1902 tree_if
*ti
= (tree_if
*) t2
;
1903 if (ti
->else_part()->count())
1905 tree_node_list
*if_body
= ti
->then_part();
1906 if (if_body
->count() != 1)
1908 tree_node
*tn
= if_body
->head()->contents
;
1909 if (tn
->kind() != TREE_LOOP
)
1911 tree_loop
*tl
= (tree_loop
*) tn
;
1913 tree_instr
*init
= (tree_instr
*)t1
;
1915 if (!init
->instr()->dst_op(0).is_symbol())
1918 *iterator
= init
->instr()->dst_op(0).symbol();
1920 tree_instr
*ti_test
= if_test(ti
->header());
1925 tree_instr
*tl_test
;
1926 if (!loop_extract_increment_and_test(tl
->test(), &tl_inc
, &tl_test
))
1929 if (ti_test
->instr()->opcode() != io_bfalse
)
1932 if (tl_test
->instr()->opcode() != io_btrue
)
1935 if (!equal(ti_test
->instr()->src_op(0), tl_test
->instr()->src_op(0)))
1938 if (!is_increment_on(tl_inc
->instr(), *iterator
))
1941 if (ti_test
->instr()->src_op(0).kind() != OPER_INSTR
)
1944 instruction
*in
= ti_test
->instr()->src_op(0).instr();
1945 if (in
->opcode() != io_sl
&& in
->opcode() != io_sle
)
1948 if (!in
->src_op(0).is_symbol())
1950 if (in
->src_op(0).symbol() != *iterator
)
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;
1960 guard_constructor
gc(sa
, verbose
, NULL
);
1961 ok
= gc
.construct_guard(in
);
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
);
1974 Relation I
= Intersection(*gc
.s
, *gc_lower
.s
);
1976 t1
->append_annote(k_for_annote
,
1977 new for_ann(new SRelation(I
, sa
), *iterator
, *body
));
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
;
1992 if (!tnli
.is_empty() &&
1993 is_broken_up_loop(t
, tnli
.peek(), &body
, &iterator
)) {
1995 sa
->vars
[iterator
]->iterator
= false;
1996 if (sa
->vars
[iterator
]->assigned
)
1997 sa
->vars
[iterator
]->valid_for_read
= false;
2003 start
= t
->list_e();
2007 if (start
->next() == t
->list_e())
2008 root
= start
->contents
;
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()) {
2022 next
= start
->next();
2026 if (!(root
->kind() == TREE_INSTR
&&
2027 ((tree_instr
*)root
)->instr()->opcode() == io_mrk
))
2028 root
->append_annote(k_static_root
, new immed_list());
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");
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
);
2051 void construct_domains(tree_proc
* tp
, int verbose
, int oldstyle
, context_info
*ctx
)
2053 domain_constructor
dc(tp
, verbose
, oldstyle
);
2058 static void free_stmt(void *data
)
2060 stmt
*s
= (stmt
*)data
;
2065 free_domain_ann(void *data
)
2067 domain_ann
*da
= (domain_ann
*) data
;
2073 free_symtab(void *data
)
2075 symtab_ann
*sa
= (symtab_ann
*) data
;
2080 static void free_srelation(void *data
)
2082 SRelation
*sr
= (SRelation
*) data
;
2086 static void free_for_ann(void *data
)
2088 delete (for_ann
*) data
;
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
);