2 /* file "named_lin_ineq.cc" */
4 /* Copyright (c) 1994 Stanford University
8 This software is provided under the terms described in
9 the "suif_copyright.h" include file. */
11 #include <suif_copyright.h>
13 #define _MODULE_ "libsuifmath.a"
14 #pragma implementation "named_lin_ineq.h"
22 int named_lin_ineq::unum_cnt
= 0;
26 /* ##################################################
27 ##### name_table_entry #####
28 ################################################## */
30 name_table_entry::~name_table_entry()
35 /***************************************************************************
37 ***************************************************************************/
39 void name_table_entry::init(const immed
& im
)
42 assert(im
.symbol()->is_var());
44 vsname
.v
= (var_sym
*)im
.symbol();
46 } else if(im
.is_string()) {
48 vsname
.s
= im
.string();
58 void name_table_entry::init(name_table_entry_kind k
,
62 // assert(knd != nte_aux);
67 void name_table_entry::set_name(const immed
& im
)
69 name_table_entry_kind kk
= kind();
71 if(kind() != nte_aux
) {
73 if((kind() == nte_aux
)||
79 /***************************************************************************
81 ***************************************************************************/
82 void name_table_entry::init(const name_table_entry
& nte
)
87 vsname
.v
= nte
.vsname
.v
;
89 vsname
.s
= nte
.vsname
.s
;
93 /***************************************************************************
94 * Following functions will change the type of a table entry *
95 ***************************************************************************/
96 void name_table_entry::mark_sym()
99 assert(knd
!= nte_aux
);
103 void name_table_entry::mark_cond()
106 assert(knd
!= nte_aux
);
110 void name_table_entry::mark_loop()
113 assert(knd
!= nte_aux
);
117 void name_table_entry::mark_dim()
120 assert(knd
!= nte_aux
);
124 void name_table_entry::mark_summary()
127 assert(knd
!= nte_aux
);
131 void name_table_entry::mark_aux()
139 /***************************************************************************
141 ***************************************************************************/
142 boolean
name_table_entry::operator==(const name_table_entry
& nte
) const
144 if((nte
.knd
!= knd
)||
147 if(is_var
&& nte
.is_var
)
148 return (var() == nte
.var()) || var()->overlaps(nte
.var());
150 return (nte
.name() == name());
154 immed
name_table_entry::name() const
158 return immed(vsname
.v
);
160 return immed(vsname
.s
);
165 const char * name_table_entry::string() const
169 return vsname
.v
->name();
175 static boolean
is_ancestor(base_symtab
* ans
, base_symtab
* chld
)
177 if(chld
== ans
) return TRUE
;
178 if(chld
->parent() == NULL
) return FALSE
;
179 return is_ancestor(ans
, chld
->parent());
183 static base_symtab
* inner_symtab(base_symtab
* st1
, base_symtab
* st2
)
185 if(is_ancestor(st1
, st2
)) return st2
;
186 if(is_ancestor(st2
, st1
)) return st1
;
187 // assert_msg(0, ("Symbols are in different scopes, no single scope that covers all the symbols used"));
192 base_symtab
* name_table_entry::get_symtab(base_symtab
* in
) const
194 if((kind() == nte_aux
)||(!is_var
))
197 base_symtab
* st
= var()->parent();
203 return inner_symtab(st
, in
);
209 /* ##################################################
210 ##### name_table #####
211 ################################################## */
213 #define SETTABLE(N) if(n() > N) { \
215 L[N-1].set_name(*(v##N));\
220 name_table::name_table(const immed
* v1
, const immed
* v2
, const immed
* v3
,
221 const immed
* v4
, const immed
* v5
, const immed
* v6
,
222 const immed
* v7
, const immed
* v8
, const immed
* v9
,
223 const immed
* v10
, const immed
* v11
, const immed
* v12
,
224 const immed
* v13
, const immed
* v14
, const immed
* v15
,
269 /***************************************************************************
271 ***************************************************************************/
272 name_table::~name_table()
278 name_table
&name_table::operator=(const name_table
&nt
)
284 /***************************************************************************
286 ***************************************************************************/
287 void name_table::resize(int newsz
)
291 int osz
= MIN(sz
,newsz
);
292 name_table_entry
*L1
= L
;
294 L
= (rsz
-1>0)?(new name_table_entry
[rsz
-1]):NULL
;
296 for(int i
=1; i
<osz
; i
++)
303 void name_table::init(const name_table
&nt
)
305 if(&nt
== this) return;
310 L
= (rsz
-1>0)?(new name_table_entry
[rsz
-1]):NULL
;
314 for(int i
=1; i
<n(); i
++)
315 L
[i
-1].init(nt
.e(i
));
318 /***************************************************************************
320 ***************************************************************************/
321 void name_table::init(int s
)
326 L
= (rsz
-1>0)?(new name_table_entry
[rsz
-1]):NULL
;
330 for(int i
=1; i
<n(); i
++)
335 /***************************************************************************
337 ***************************************************************************/
338 int name_table::find(const name_table_entry
& nte
) const
340 for(int i
=1; i
<n(); i
++)
341 if(L
[i
-1] == nte
) return i
;
346 /***************************************************************************
348 ***************************************************************************/
349 int name_table::find(const immed
& v
) const
351 for(int i
=1; i
<n(); i
++)
352 if(L
[i
-1].name() == v
) return i
;
356 constraint
name_table::lio_code_type() const
360 for(int i
=1; i
<n(); i
++)
361 switch(e(i
).kind()) {
378 void name_table::remove(int i
, int j
)
380 assert((0<i
)&&(i
<=j
)&&(j
<n()));
392 void name_table::remove(const integer_row
& mask
)
395 assert(mask
.n() == n());
397 for (dst
=1, src
=1; (src
< n()); src
++) {
407 void name_table::insert(const name_table_entry
& nte
, int i
)
409 assert((i
>=1)&&(i
<=n()));
411 int lln
= MAX(n()-1+1,(n()-1)*2);
412 name_table_entry
* LL
= (lln
>0)?(new name_table_entry
[lln
]):NULL
;
426 for (int k
=sz
; k
>i
; k
--)
433 void name_table::insert(const immed
& v
, int i
)
435 insert(name_table_entry(v
), i
);
440 /***************************************************************************
441 * use B and change A *
442 ***************************************************************************/
443 void name_table::change_name_types(name_table
& na
, name_table
& nb
)
445 for(int i
=1; i
<nb
.n(); i
++) {
446 immed
bv(nb
.e(i
).name());
447 if(bv
.is_symbol() || bv
.is_string()) { // not an aux
450 name_table_entry_kind ka
= na
.e(j
).kind();
451 name_table_entry_kind kb
= nb
.e(i
).kind();
452 name_table_entry_kind kk
= nte_none
;
455 else if(ka
== nte_none
)
457 else if(kb
== nte_none
) /* can't happen */
459 else if(ka
== nte_symconst
)
461 else if(kb
== nte_symconst
)
463 else if((ka
== nte_cond
)&&(kb
== nte_loop
))
465 else if((kb
== nte_cond
)&&(ka
== nte_loop
))
467 else if((ka
== nte_summary
)||(kb
== nte_summary
))
479 /***************************************************************************
481 ***************************************************************************/
482 boolean
name_table::is_aligned(const name_table
& na
,
483 const name_table
& nb
)
485 if(na
.n() != nb
.n()) return FALSE
;
487 for(int i
=1; i
<na
.n(); i
++) {
488 if(na
.e(i
).name() != nb
.e(i
).name())
489 if (na
.e(i
).kind() != nte_summary
)
491 if(na
.e(i
).name() == immed(0))
493 else if(na
.e(i
).kind() != nb
.e(i
).kind())
496 // make sure table is ordered;
497 name_table_entry_kind oldkind
=nte_none
;
498 for (int j
=1; j
<na
.n(); j
++) {
499 name_table_entry_kind newkind
=na
.e(j
).kind();
502 if (oldkind
== nte_cond
) return FALSE
;
504 if (oldkind
== nte_loop
) return FALSE
;
506 if (oldkind
== nte_dim
) return FALSE
;
508 if (oldkind
== nte_summary
) return FALSE
;
510 if (oldkind
== nte_aux
) return FALSE
;
522 /***************************************************************************
524 ***************************************************************************/
525 name_table
name_table::operator&(const name_table
& b
) const
527 name_table
ret(this);
532 /***************************************************************************
534 ***************************************************************************/
535 name_table
&name_table::operator&=(const name_table
& b
)
537 if(is_aligned(*this, b
)) {
541 integer_row
cb(b
.n());
542 this->align_with(b
,ca
,cb
);
546 /***************************************************************************
548 ***************************************************************************/
549 name_table
* name_table::align_tables(const name_table
&na
,
550 const name_table
&nb
,
554 name_table
*newnt
= new name_table(na
);
556 newnt
->align_with(nb
, ca
, cb
);
561 /***************************************************************************
563 ***************************************************************************/
564 void name_table::align_with(const name_table
&nb
,
569 name_table
nbcopy(nb
);
570 assert(n() == ca
.n());
571 assert(nb
.n() == cb
.n());
572 change_name_types(*this, nbcopy
);
574 for(ii
=1; ii
<n(); ii
++)
575 assert(e(ii
).kind() != nte_none
);
576 for(ii
=1; ii
<nbcopy
.n(); ii
++)
577 assert(nbcopy
.e(ii
).kind() != nte_none
);
579 ca
[0] = cb
[0] = 0; // consant position does not change
581 for (ii
=1; ii
<ca
.n(); ii
++)
585 for (ii
=1; ii
< nbcopy
.n(); ii
++) {
586 if ((cb
[ii
] = find(nbcopy
.e(ii
))) == -1)
592 for (ii
=1; ii
< nbcopy
.n(); ii
++) {
593 if ((cb
[ii
]) == -1) {
594 (*this)[curr
] = nbcopy
.e(ii
);
598 integer_row
extrac(n());
599 if (do_reorder_table(extrac
)) {
600 integer_row
newca(ca
.n()), newcb(cb
.n());
601 for (ii
=1; ii
< ca
.n(); ii
++) {
602 // was: this[ca[ii]] = old[ii];
603 // becomes: this[extrac[ii]] =
604 // ii moves to elt extrac[ca[ii]]
605 newca
[ii
] = extrac
[ca
[ii
]];
608 for (ii
=1; ii
< cb
.n(); ii
++) {
609 newcb
[ii
] = extrac
[cb
[ii
]];
615 static void find_elements(name_table_entry_kind k
,
616 const name_table
&na
, integer_row
&ca
,
620 for (int ai
=1; ai
<na
.n(); ai
++) {
621 if (na
.e(ai
).kind()==k
) {
629 boolean
name_table::do_reorder_table(integer_row
&ca
)
632 assert(ca
.n() == n());
633 find_elements(nte_symconst
, *this, ca
, curr
);
634 find_elements(nte_cond
, *this, ca
, curr
);
635 find_elements(nte_loop
, *this, ca
, curr
);
636 find_elements(nte_dim
, *this, ca
, curr
);
637 find_elements(nte_summary
, *this, ca
, curr
);
638 find_elements(nte_aux
, *this, ca
, curr
);
639 assert(curr
== ca
.n());
641 name_table
thiscopy(*this);
643 for (i
=1; i
<n(); i
++)
644 (*this)[ca
[i
]] = thiscopy
[i
];
645 for (i
=1; i
<n(); i
++)
651 /***************************************************************************
653 ***************************************************************************/
654 name_table
* name_table::mk_align(const name_table
& na
,
655 const name_table
& nb
)
658 if(is_aligned(na
, nb
))
659 newnt
= new name_table(na
);
661 // indexes to the new list
662 integer_row
ca(na
.n());
663 integer_row
cb(nb
.n());
665 newnt
= name_table::align_tables(na
, nb
, ca
, cb
);
671 base_symtab
* name_table::get_symtab(base_symtab
* in
) const
673 base_symtab
* curr
= in
;
674 for(int i
=1; i
<n(); i
++)
675 curr
= e(i
).get_symtab(curr
);
683 /* ##################################################
684 ##### named_lin_ineq #####
685 ################################################## */
687 /***************************************************************************
689 ***************************************************************************/
690 named_lin_ineq::~named_lin_ineq()
695 void named_lin_ineq::init()
700 void named_lin_ineq::init(int m
, int n
)
707 /***************************************************************************
709 ***************************************************************************/
710 void named_lin_ineq::init(const named_lin_ineq
& c
)
717 int named_lin_ineq::init(const immed_list
& il
, int c
)
719 unum
= il
[c
++].integer();
720 unum_cnt
= MAX(unum_cnt
, unum
+1);
722 int num
= il
[c
++].integer();
725 for(int i
=1; i
<num
; i
++)
726 names()[i
].init((name_table_entry_kind
)il
[c
++].integer(),il
[c
++]);
727 c
= ineqs().integer_matrix::init(il
, c
);
731 immed_list
* named_lin_ineq::cvt_immed_list() const
733 immed_list
* L
= new immed_list
;
735 L
->append(immed(uid()));
736 L
->append(immed(n()));
737 for(int i
=1; i
<n(); i
++) {
738 L
->append(immed((int)const_names().e(i
).kind()));
739 L
->append(const_names().e(i
).name());
741 immed_list
* iq
= const_ineqs().cvt_immed_list();
746 void named_lin_ineq::swap_col(int i
, int j
)
748 name_table_entry
tmp(names()[i
]);
749 names()[i
].init(names()[j
]);
750 names()[j
].init(tmp
);
752 if(ineqs().m() > 0) {
753 assert(names().n() == ineqs().n());
754 lq
.do_swap_col(i
, j
);
758 void named_lin_ineq::del_col(int i
, int j
)
761 assert((i
>0)&&(j
>0));
762 assert((i
<n())&&(j
<n()));
769 void named_lin_ineq::del_col(const integer_row
& rem
)
771 assert(rem
.n() == n());
773 ineqs().do_del_columns(rem
);
774 assert(names().n() == ineqs().n());
777 boolean
named_lin_ineq::is_clean_false() const
779 if ((m()==1) && (n()==1) && (const_ineqs().r(0).c(0) < 0))
785 static void normalize_aux_offset(lin_ineq
&leq
, int auxcol
)
789 for (int i1
=0; i1
<leq
.m(); i1
++) {
790 const integer_row
&rowi
= leq
.r(i1
);
791 int coeff
= rowi
.c(auxcol
);
793 if ((bestcoeff
<= 0) || (coeff
< bestcoeff
)) {
797 } else if (coeff
< 0) {
798 if ((bestcoeff
== 0) || (coeff
> bestcoeff
)) {
805 int bestconst
= leq
[bestrow
][0];
806 int abscoeff
= ABS(bestcoeff
);
807 int newconst
= bestconst
% abscoeff
;
808 newconst
= (newconst
> 0) ? newconst
: newconst
+ abscoeff
;
809 int constdiff
= (newconst
- bestconst
)/bestcoeff
;
811 for (int i2
=0; i2
<leq
.m(); i2
++) {
812 int coeffi
= leq
[i2
][auxcol
];
814 leq
[i2
][0] += constdiff
* coeffi
;
819 void named_lin_ineq::cleanup()
826 if (is_clean_false()) return;
828 if(~ineqs() == TRUE
) {
832 init(named_lin_ineq(nt0
, leq0
));
836 integer_row
rem(n());
838 boolean remmed
= FALSE
;
840 // remove aux vars that are empty.
841 // also remove aux vars that are multiple of 1
842 // also remove auxes which are only a lower or upper bound
843 for(int i
=1; i
<n(); i
++)
844 if(names()[i
].kind() == nte_aux
) {
845 boolean zero_or_one
= TRUE
;
850 for(int j
=0; (j
<ineqs().m()); j
++)
851 if(ineqs()[j
][i
] != 0) {
852 if (ineqs()[j
][i
] > 0) {
859 if (ABS(ineqs()[j
][i
]) > 1)
863 "\n### Warning: bad aux var ineq in cleanup\n");
867 if (zero_or_one
|| (upper_bds
== 0) || (lower_bds
== 0))
868 rem
[i
] = remmed
= TRUE
;
869 else if ((upper_bds
== 1) && (lower_bds
== 1)) {
870 constraint
upper_bd(ineqs()[upper_row
]);
871 constraint
lower_bd(ineqs()[lower_row
]);
872 upper_bd
+= ineqs()[lower_row
];
873 if (upper_bd
.rank() == 0) {
874 int diffi
= ineqs()[upper_row
][0] + ineqs()[lower_row
][0];
875 int mult
= ineqs()[lower_row
][i
];
876 if (ABS(diffi
) >= mult
-1) {
877 // S has aux X with only constraints
878 // c1 <= Y + mX <= c2 where c2-c1 >= m,
879 // so remove X and its constraints
880 rem
[i
] = remmed
= TRUE
;
886 // check if two auxilary vars are doing the same job
887 for(int i1
=1; i1
<n(); i1
++)
888 if((names()[i1
].kind() == nte_aux
)&&(!rem
[i1
]))
889 for(int i2
=i1
+1; i2
<n(); i2
++)
890 if((names()[i2
].kind() == nte_aux
)&&(!rem
[i2
])) {
891 constraint
filter(n());
894 filter
[i2
] = 1; // c1*i1=a(); c2*i2=b()
895 // get rows with occurrences of i1 or i2;
896 lin_ineq L
= ineqs().filter_thru(filter
, 0);
897 // assert(!(~L)); // has to have an answer
901 L
[L
.m()-1][i1
] = 1; // if both are the same
902 L
[L
.m()-1][i2
] = -1; // c1 > c2 is empty
904 L
[L
.m()-1][i1
] = -1; // and c2 > c1 is empty
906 if(~L
) rem
[i2
] = remmed
= TRUE
;
911 ineqs().do_filter_away(rem
,0);
915 // canonicalize aux offsets;
916 for(int i3
=1; i3
<n(); i3
++)
917 if (names()[i3
].kind() == nte_aux
)
918 normalize_aux_offset(ineqs(),i3
);
921 void named_lin_ineq::simplify()
923 ineqs().normalize(TRUE
);
925 ineqs().del_repetition();
931 void named_lin_ineq::del_zero_cols()
933 integer_row
zeros(n());
935 for(int i
=n()-1; i
>=1; i
--) {
936 int zero
= zeros
[i
] = 1;
937 for(int j
=0; zero
&& (j
<ineqs().m()); j
++)
938 if(ineqs()[j
][i
] != 0) {
946 named_lin_ineq
& named_lin_ineq::operator=(const named_lin_ineq
& c
)
948 if(&c
== this) return *this;
955 named_lin_ineq
& named_lin_ineq::operator=(const lin_ineq
& l
)
957 assert(l
.n() == names().n());
962 void named_lin_ineq::align_named_lin_ineqs(named_lin_ineq
& A
,
968 boolean
named_lin_ineq::operator==(const named_lin_ineq
& c2
) const
970 if((this->const_ineqs().m() == 0)&&(c2
.const_ineqs().m() == 0))
972 if((this->const_ineqs().m() == 0)||(c2
.const_ineqs().m() == 0))
977 boolean delend
= FALSE
;
979 if(is_aligned(*this, c2
)) {
980 l1
= (named_lin_ineq
*)this;
981 l2
= (named_lin_ineq
*)&c2
;
983 l1
= new named_lin_ineq(this);
984 l2
= new named_lin_ineq(c2
);
989 boolean ret
= (((*l1
) >> (*l2
))&&
1000 named_lin_ineq
named_lin_ineq::operator&(const named_lin_ineq
& c
) const
1004 return named_lin_ineq();
1007 else if (c
.m() == 0)
1009 else if (is_aligned(*this, c
)) {
1010 named_lin_ineq
a1(this);
1011 a1
&= c
.const_ineqs();
1014 named_lin_ineq
a1(this);
1015 named_lin_ineq
a2(c
);
1018 a1
&= a2
.const_ineqs();
1023 // Deletes are there to save memory
1024 named_lin_ineq
* named_lin_ineq::and2(named_lin_ineq
* c1
,
1025 named_lin_ineq
* c2
,
1031 named_lin_ineq
* ret
= new named_lin_ineq(c1
);
1037 if (del1
) return c1
;
1039 return new named_lin_ineq(c1
);
1045 return new named_lin_ineq(c2
);
1051 named_lin_ineq
& named_lin_ineq::operator&=(const named_lin_ineq
& c
)
1053 named_lin_ineq
cc(c
);
1054 this->align_with(cc
);
1055 (*this) &= cc
.ineqs();
1060 named_lin_ineq
& named_lin_ineq::operator&=(const lin_ineq
& l
)
1062 assert(l
.n() == names().n());
1068 // get rid of linearly dependent new rows;
1069 ineqs().del_repetition(oldm
, m()-1);
1070 ineqs().del_loose(oldm
, m()-1);
1075 // Given lower and upper bounds for two seperate aux vars
1076 // see if they can be combined toghter to form a single aux var
1077 // returns TRUE if it works, and swaps i1 and i2 in bounds2;
1078 boolean
nli_merged_aux(lin_ineq
& bounds1
, lin_ineq
& bounds2
,
1081 if (bounds1
.m() != bounds2
.m()) return FALSE
;
1083 bounds2
.do_swap_col(i1
, i2
);
1085 // faster approximation to bounds1[1:n-1] == bounds2[1:n-1];
1086 integer_row
used(bounds2
.m());
1088 int m
= bounds1
.m();
1089 int n
= bounds1
.n();
1090 for (i
=0; i
<m
; i
++) {
1091 for (j
=0; j
<m
; j
++) {
1093 const constraint
&b1
= bounds1
.r(i
);
1094 const constraint
&b2
= bounds2
.r(j
);
1096 // ignore constant term;
1097 for (k
=1; k
<n
; k
++) {
1098 if (b1
.c(k
) != b2
.c(k
))
1109 bounds2
.do_swap_col(i1
,i2
);
1119 if ((bounds1 <= bounds2) &&
1120 (bounds2 <= bounds1)) {
1124 bounds2.do_swap_col(i1, i2);
1129 int named_lin_ineq::merge_auxes(named_lin_ineq
&c
)
1131 named_lin_ineq
*r1
= this;
1132 named_lin_ineq
*r2
= &c
;
1134 // do we need these?
1135 r1
->del_zero_cols();
1136 r2
->del_zero_cols();
1138 r1
->align_with(*r2
);
1141 constraint
indx(r1
->n());
1144 // count the number of aux variables and record their positions
1145 for(i
=1; i
<r1
->n(); i
++)
1146 if(r1
->names()[i
].kind() == nte_aux
) {
1152 // For each aux variable, find the lower bounds and the upper bounds
1153 // BUGBUG: ignore relations between different aux vars for now;
1154 // this is conservative, at least;
1155 lin_ineq
* baux1
= new lin_ineq
[naux
];
1156 lin_ineq
* baux2
= new lin_ineq
[naux
];
1157 constraint
kernel(r1
->n());
1158 constraint
kernel2(r1
->n());
1161 for(i
=0; i
<naux
; i
++) {
1165 for(i
=0; i
<naux
; i
++) {
1169 baux1
[i
].init(r1
->ineqs().filter_thru(kernel
, 0));
1170 baux1
[i
].init(baux1
[i
].filter_away(kernel2
, 0));
1171 baux2
[i
].init(r2
->ineqs().filter_thru(kernel
, 0));
1172 baux2
[i
].init(baux2
[i
].filter_away(kernel2
, 0));
1177 // See if two aux variables can be merged toghter.
1178 // one var has to be of r1 and other has to be of r2
1179 // ignore aux interactions for now;
1181 integer_row
rmauxlist(r1
->n());
1182 for (i
=0; i
<naux
; i
++)
1183 if (baux1
[i
].m()>0) {
1184 for (j
=0; j
<naux
; j
++)
1185 if (baux2
[j
].m()>0) {
1189 // try to equate ix(in 1) and jx(in 2);
1190 if (nli_merged_aux(baux1
[i
], baux2
[j
], ix
, jx
)) {
1191 // merge found, record it and
1192 // mark the aux to be removed.
1195 r2
->ineqs().do_swap_col(ix
,jx
);
1205 if (mergedaux
> 0) {
1206 r1
->del_col(rmauxlist
);
1207 r2
->del_col(rmauxlist
);
1214 // err towards FALSE;
1215 boolean
named_lin_ineq::operator>=(const named_lin_ineq
& c
) const
1217 named_lin_ineq
l1(*this);
1218 named_lin_ineq
l2(c
);
1224 // do we need these?
1228 const name_table
&nt1
= l1
.const_names();
1229 const name_table
&nt2
= l2
.const_names();
1231 // count the number of aux variables;
1232 for(i
=1; i
<nt1
.n(); i
++) {
1233 const name_table_entry
&ntei
= nt1
.e(i
);
1234 if(ntei
.kind() == nte_aux
) {
1236 } else if (nt2
.find(ntei
) < 0)
1237 // this constrains a variable not constrained by c;
1238 // so there is no way this contains c;
1242 for(i
=1; i
<nt2
.n(); i
++) {
1243 const name_table_entry
&ntei
= nt2
.e(i
);
1244 if(ntei
.kind() == nte_aux
)
1248 if (naux1
> naux2
) return FALSE
; // same problem with this;
1251 int mergedauxes
= l1
.merge_auxes(l2
);
1253 if (naux1
> mergedauxes
) return FALSE
;
1255 // BUGBUG; still doesnt handle auxes right in general;
1256 // consider { x = 2*aux } and { x = 4*aux };
1260 if(~(l1
.ineqs() && l2
.ineqs())) {
1263 boolean ret
= (l1
.ineqs() >= l2
.ineqs());
1267 /**************************************************************************
1268 * a simple substitution method *
1269 * This is a cheap alternative to expensive Fourier-Motzkin *
1270 * substitution expression given in expr is of the form *
1271 * var >= sub_expr and var <= sub_expr or *
1273 **************************************************************************/
1274 named_lin_ineq
* named_lin_ineq::substitute(const immed
& var
,
1275 const named_lin_ineq
& expr
) const
1277 named_lin_ineq
*ret
= new named_lin_ineq(this);
1278 ret
->do_substitute(var
, expr
);
1282 void named_lin_ineq::do_substitute(const immed
& var
,
1283 const named_lin_ineq
& expr
)
1285 int pos
= find(var
);
1289 int col
= expr
.find(var
);
1293 tested
&= (expr
.m() == 2);
1294 tested
&= ABS(expr
.const_ineqs().r(0).c(col
) == 1);
1295 for(int i
=0; tested
&& i
<expr
.n(); i
++)
1297 (expr
.const_ineqs().r(0).c(i
) + expr
.const_ineqs().r(1).c(i
) == 0);
1298 assert_msg(tested
,("do_substitute, expr not of right form"));
1300 // leave in row with -var;
1301 int row
= (expr
.const_ineqs().r(0).c(col
) > 0) ? 0 : 1;
1302 named_lin_ineq
myex(expr
);
1304 myex
.ineqs().do_del_row(row
);
1308 for(int im
=0; im
<m(); im
++) {
1309 int coeff
= ineqs()[im
][pos
];
1311 ineqs()[im
].do_addmul(myex
.ineqs()[0], coeff
);
1312 ineqs()[im
][pos
] = 0;
1319 void named_lin_ineq::find_bounds()
1321 poly_iterator
Poly(ineqs());
1322 constraint
del_list(ineqs().n());
1324 for(int a
=1; a
< ineqs().n(); a
++)
1325 if(names()[a
].kind() == nte_symconst
)
1327 // sort by symconsts, then by rank;
1328 Poly
.set_sort_order(del_list
.data_array());
1331 // fm-pairwise project ineqs, sort them;
1332 lin_ineq
*M
= Poly
.get_iterator(0);
1334 // try to get rid of some of the extra constraints;
1335 M
= Poly
.reduce_extra_constraints2_ptr();
1343 void named_lin_ineq::add_col(const name_table_entry
& nte
, int i
)
1345 names().insert(nte
, i
);
1346 ineqs().do_insert_col(i
);
1347 assert(ineqs().n() == names().n());
1351 void named_lin_ineq::project()
1353 constraint
del_list(n());
1356 // sort order is approximately;
1357 // symbolic constants eqns last, then others vaguely by rank;
1358 // (really something close to (rank+sum(i+1 | col i is non-0)));
1359 for(int a
=1; a
<n(); a
++)
1360 if(names()[a
].kind() == nte_symconst
)
1366 poly_iterator
Poly(ineqs());
1367 Poly
.set_sort_order(del_list
.data_array());
1368 Poly
.get_iterator(1);
1369 ineqs().init(Poly
.reduce_extra_constraints2_ptr());
1375 void named_lin_ineq::project_away(const immed
& var
, int *changedp
)
1378 N
.insert(name_table_entry(var
), 1);
1379 project_away(N
, changedp
);
1382 extern lin_ineq
* fast_fourier_motzkin(lin_ineq
& in
, integer_row
*elim
= 0,
1383 boolean iterate
=TRUE
);
1385 static void del_unit_stride_rows(lin_ineq
&lq
,
1386 const integer_row
&elim
)
1389 integer_row
delrows(lq
.m());
1390 for (j
=0; j
<lq
.n(); j
++) {
1392 for (i
=0; i
<lq
.m(); i
++) {
1393 int entry
= lq
[i
][j
];
1395 if (ABS(entry
) <= 1)
1396 delrows
[i
]=1; // do del it;
1399 lq
.do_del_rows(delrows
);
1402 int use_alt_project
= 0;
1403 int debug_suifmath_project
= 0;
1405 void named_lin_ineq::project_away(const name_table
& N
, int *changed
)
1407 constraint
elim(n());
1411 for(i
=1; i
<N
.n(); i
++) { // for each name to be deleted
1412 int pos
= names().find(N
.e(i
).name()); // position of that name
1413 if ((pos
> 0) && !elim
[pos
]) {
1414 elim
[pos
] = 1; // filter anything in that pos;
1415 swap_col(pos
, n()-j
); // switch it to the end;
1416 elim
.do_swap_col(pos
, n()-j
);
1420 if (j
==1) return; // nothing to project;
1421 if (changed
) *changed
= 1;
1423 // look for existing aux vars; eliminate them, too;
1424 for(i
=1; i
<n(); i
++) {
1425 if (names()[n()-i
].kind() == nte_aux
) {
1427 swap_col(n()-i
, n()-j
);
1435 lin_ineq involved
= ineqs().filter_thru(elim
,0);
1436 if (involved
.m() > 0) {
1437 ineqs().do_filter_away(elim
,0);
1438 if (debug_suifmath_project
) {
1439 fprintf(stderr
,"for_project: filtering away, elim:\n");
1441 fprintf(stderr
,"uninvolved:\n");
1442 ineqs().print(stderr
);
1443 fprintf(stderr
,"involved:\n");
1444 involved
.print(stderr
);
1447 fast_fourier_motzkin(involved
, &elim
, (use_alt_project
> 1));
1448 if (debug_suifmath_project
) {
1449 fprintf(stderr
,"after projection:\n");
1450 projeq
->print(stderr
);
1452 if (use_alt_project
> 0) {
1453 del_unit_stride_rows(*projeq
, elim
);
1454 if (debug_suifmath_project
) {
1455 fprintf(stderr
,"after unit rows deleted:\n");
1456 projeq
->print(stderr
);
1458 constraint
noelim(n());
1462 projeq
->do_filter_thru(noelim
,0);
1464 projeq
->do_filter_away(elim
,0);
1466 if (debug_suifmath_project
) {
1467 fprintf(stderr
,"after uninteresting rows deleted:\n");
1468 projeq
->print(stderr
);
1471 if (debug_suifmath_project
) {
1472 fprintf(stderr
,"replacing uninvolved rows:\n");
1473 ineqs().print(stderr
);
1475 delete projeq
; projeq
= 0;
1476 for (i
=0; i
<n(); i
++) {
1478 names()[i
].mark_aux();
1480 if (debug_suifmath_project
) {
1481 fprintf(stderr
,"before cleanup:\n");
1487 ineqs().del_repetition();
1488 ineqs().del_loose();
1493 boolean
named_lin_ineq::operator~() const
1495 return ~const_ineqs();
1498 /***************************************************************************
1500 ***************************************************************************/
1501 void named_lin_ineq::print(FILE *fp
) const
1503 // fprintf(fp, " ");
1504 // for(int i=1; i<names().n(); i++) {
1505 // fprintf(fp, "%6s",
1506 // (names()[i].map())?names()[i].map()->name():" ");
1507 // fprintf(fp, "%s", (names()[i].kind() == nte_loop)?".":" ");
1509 // for(; i<9; i++) fprintf(fp, " ");
1510 // fprintf(fp, "%3d %s <%X>\n", uid(), (is_killed()?"XXX":" "),
1513 fprintf(fp
, "[%6d] ", unum
);
1515 for(i
=1; i
<const_names().n(); i
++)
1517 (const_names().e(i
).string())?const_names().e(i
).string():
1520 for(i
=1; i
<const_names().n(); i
++) {
1522 switch(const_names().e(i
).kind()) {
1523 case nte_none
: c
= '?'; break;
1524 case nte_symconst
: c
= 's'; break;
1525 case nte_cond
: c
= 'c'; break;
1526 case nte_loop
: c
= 'l'; break;
1527 case nte_dim
: c
= 'd'; break;
1528 case nte_summary
: c
= 'y'; break;
1529 case nte_aux
: c
= 'a'; break;
1531 fprintf(fp
,"%c", c
);
1534 const_ineqs().print(fp
);
1538 void named_lin_ineq::print_exp(print_exp_type type
, FILE *fp
) const
1540 if(type
== pet_single
) assert(const_ineqs().m() == 1);
1542 for(int x
=0; x
<const_ineqs().m(); x
++) {
1547 if(const_ineqs().m() > 1)
1552 if((const_ineqs().m() > 1) && (x
==0))
1553 fprintf(fp
, "%s(", (type
==pet_min
)?"MIN":"MAX");
1560 integer_row R
= const_ineqs().r(x
);
1562 fprintf(fp
, "%d ", R
[0]);
1566 for(int i
=1; i
<n(); i
++)
1571 } else if(R
[i
] == -1) {
1576 } else if(R
[i
] > 0) {
1578 fprintf(fp
, "+ %d", R
[i
]);
1580 fprintf(fp
, "%d", R
[i
]);
1583 fprintf(fp
, "- %d", -R
[i
]);
1585 fprintf(fp
, "%d", R
[i
]);
1587 fprintf(fp
, "%s ", const_names().e(i
).string());
1590 if(pr
==0) fprintf(fp
, "0 ");
1593 fprintf(fp
, ">= 0");
1594 if(const_ineqs().m() > 1) fprintf(fp
, ")");
1595 if(x
< const_ineqs().m()-1)
1599 fprintf(fp
, ">= 0\n");
1603 if(x
< const_ineqs().m()-1)
1605 if((const_ineqs().m() >1)&&(x
== const_ineqs().m()-1))
1615 instruction
* named_lin_ineq::mk_bounds() const
1618 constraint
filter(n());
1621 for(i
=1; i
<n(); i
++)
1622 if(const_names().e(i
).kind() == nte_aux
)
1624 lin_ineq Laux
= const_ineqs().filter_thru(filter
, -1);
1625 // only A - aux >= 0
1626 lin_ineq Lbounds
= const_ineqs().filter_away(filter
, 0);
1628 boolean first
= TRUE
;
1630 for(i
=0; i
<Lbounds
.m(); i
++) {
1631 block
stmt(Lbounds
[i
][0]);
1632 for(int j
=1; j
<n(); j
++)
1633 if(const_names().e(j
).kind() != nte_aux
) {
1634 int val
= Lbounds
[i
][j
];
1635 block
sym((var_sym
*)const_names().e(j
).name().symbol());
1637 stmt
.set(stmt
+ sym
);
1639 stmt
.set(stmt
- sym
);
1641 stmt
.set(stmt
+ block(val
)*sym
);
1644 bnf
.set(stmt
>= block(0));
1647 bnf
.set(bnf
& (stmt
>= block(0)));
1650 for(i
=0; i
<Laux
.m(); i
++) {
1651 block
stmt(Laux
[i
][0]);
1653 for(int j
=1; (j
<n())&&(!done
); j
++) {
1654 int val
= Laux
[i
][j
];
1655 if(const_names().e(j
).kind() != nte_aux
) {
1656 block
sym((var_sym
*)const_names().e(j
).name().symbol());
1658 stmt
.set(stmt
+ sym
);
1660 stmt
.set(stmt
- sym
);
1662 stmt
.set(stmt
+ block(val
)*sym
);
1666 bnf
.set((stmt
% block(-val
)) == block(0));
1669 bnf
.set(bnf
& ((stmt
% block(-val
)) == block(0)));
1674 base_symtab
* bs
= const_names().get_symtab();
1676 instruction
* ins
= bs
? bnf
.make_instruction((block_symtab
*)bs
) : 0;
1681 instruction
* named_lin_ineq::create_expression(const immed
& v
,
1683 block_symtab
* sym
) const
1685 assert(const_ineqs().m() > 0);
1690 sym
= (block_symtab
*)const_names().get_symtab();
1694 constraint
filter(n());
1697 lin_ineq L
= const_ineqs().filter_thru(filter
, (is_ub
)?-1:1);
1701 for(int i
=0; i
<L
.m(); i
++) {
1702 block
curr(L
[i
][0]);
1703 int val
= -1*L
[i
][pos
];
1705 for(int j
=1; j
<n(); j
++)
1706 if(const_names().e(j
).name().is_symbol() ||
1707 const_names().e(j
).name().is_string()) {
1708 block
var((var_sym
*)const_names().e(j
).name().symbol());
1710 curr
.set(curr
+ var
);
1711 else if(L
[i
][j
] == -1)
1712 curr
.set(curr
- var
);
1713 else if(L
[i
][j
] != 0)
1714 curr
.set(curr
+ block(L
[i
][j
])*var
);
1717 curr
.set(block::op(curr
,
1718 (is_ub
)?bop_divfloor
:bop_divceil
,
1723 exp
.set(block::op(exp
, (is_ub
)?bop_min
:bop_max
, curr
));
1725 instruction
* ret
= exp
.make_instruction(sym
);
1731 /***************************************************************************
1733 ***************************************************************************/
1734 boolean
named_lin_ineq::is_aligned(const named_lin_ineq
& A
,
1735 const named_lin_ineq
& B
)
1737 const name_table
& na
= A
.const_names();
1738 const name_table
& nb
= B
.const_names();
1740 return name_table::is_aligned(na
, nb
);
1744 /***************************************************************************
1746 ***************************************************************************/
1747 void named_lin_ineq::align(const name_table
& ant
)
1749 if(name_table::is_aligned(ant
, names())) return;
1751 named_lin_ineq
tmp(this);
1752 integer_row
rmap(n());
1755 for(i
=1; i
<n(); i
++) {
1756 assert_msg(names()[i
].kind() != nte_aux
,
1757 ("Handling aux. vars. is not implemented"));
1758 int x
= ant
.find(names()[i
]);
1759 assert_msg(x
> 0, ("The variable %s is not in align name table",
1760 names()[i
].string()));
1765 ineqs().init(m(), ant
.n());
1767 for(i
=0; i
<m(); i
++)
1768 for(int j
=0; j
<tmp
.n(); j
++)
1769 ineqs()[i
][rmap
[j
]] = tmp
.ineqs()[i
][j
];
1773 /***************************************************************************
1775 ***************************************************************************/
1776 void named_lin_ineq::align_with(named_lin_ineq
& B
)
1778 named_lin_ineq
& A
= *this;
1779 if(is_aligned(A
,B
)) return;
1784 name_table
& na
= A
.names();
1785 name_table
& nb
= B
.names();
1787 // indexes to the new list
1788 integer_row
ca(na
.n());
1789 integer_row
cb(nb
.n());
1791 name_table
* newnt
= name_table::align_tables(na
, nb
, ca
, cb
);
1796 // Readjust the inequalities to match the new name table
1797 lin_ineq
leqa(A
.lq
.m(), newnt
->n());
1799 for(i
=0; i
<A
.lq
.m(); i
++)
1800 for(int j1
=0; j1
<A
.lq
.n(); j1
++)
1801 leqa
[i
][ca
[j1
]] = A
.lq
[i
][j1
];
1804 lin_ineq
leqb(B
.lq
.m(), newnt
->n());
1805 for(i
=0; i
<B
.lq
.m(); i
++)
1806 for(int j2
=0; j2
<B
.lq
.n(); j2
++)
1807 leqb
[i
][cb
[j2
]] = B
.lq
[i
][j2
];
1813 // reorders the table so element kind ordering matches historical ordering;
1814 // if ca, then sets ca so that new[*ca[i]] = old[i];
1815 void named_lin_ineq::do_reorder_table(integer_row
*retca
)
1817 integer_row
ca(n());
1818 boolean changed
= nt
.do_reorder_table(ca
);
1821 integer_row
tmp(n());
1822 for (int j
=0; j
<m(); j
++) {
1823 constraint
&rowj
= lq
[j
];
1825 for (int i
=1; i
<n(); i
++)
1826 tmp
[ca
[i
]] = rowj
[i
];
1830 if (retca
) retca
->init(ca
);
1834 /***************************************************************************
1836 ***************************************************************************/
1837 named_lin_ineq
* named_lin_ineq::merge_named_lin_ineqs(
1838 const named_lin_ineq
& A
, const named_lin_ineq
& B
)
1840 named_lin_ineq
* nA
= new named_lin_ineq(A
);
1841 named_lin_ineq
* nB
= new named_lin_ineq(B
);
1842 align_named_lin_ineqs(*nA
, *nB
);
1844 (*nA
) &= nB
->ineqs();
1854 /* ##################################################
1855 ##### other routines for debugging only #####
1856 ################################################## */
1858 /***************************************************************************
1860 ***************************************************************************/
1861 void name_table_entry::print(FILE * fp
) const
1863 // fprintf(fp, "(");
1866 // fprintf(fp, "n ");
1868 // case nte_symconst:
1869 // fprintf(fp, "s ");
1872 // fprintf(fp, "c ");
1875 // fprintf(fp, "l ");
1878 // fprintf(fp, "? ");
1884 // fprintf(fp, "?");
1885 // fprintf(fp, " ");
1886 // if(old_name) old_name->print();
1887 // fprintf(fp, ")");
1888 fprintf(fp
, "%s ", (string())?string():"?");
1892 void name_table::print(FILE * fp
) const
1894 for(int i
=1; i
<n(); i
++) e(i
).print(fp
);
1899 void name_table::print_symtabs(FILE * fp
) const
1902 for(int i
=1; i
<n(); i
++) {
1904 fprintf(fp
, "%7s", e(i
).vsname
.v
->parent()->name());