o_const.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
---------------------------> Sather 1.1 source file <--------------------------

class OPT_CONST

class OPT_CONST is include OPT_HELPER; -- moves constant expressions out of the loop, and moves while! and until! -- iters from the beginning of the loop to the end. This may help in hoisting -- either constants or iter initializations. const_hoisting(func:AM_ROUT_DEF,pass:INT) is d::=const_hoisting(func,pass);-- OPT_CONST::const_hoisting end; const_hoisting(func:AM_ROUT_DEF,pass:INT):BOOL is c::=#AM_CURSOR(prog,func.code);-- AM_CURSOR::create OPT_CONST::prog AM_ROUT_DEF::code c.ignore_pre:=true;-- AM_CURSOR::ignore_pre c.ignore_post:=true;-- AM_CURSOR::ignore_post c.ignore_assert:=true;-- AM_CURSOR::ignore_assert res:BOOL:=false; after_loop_break:ARRAY{BOOL}:=#(30); -- not more than 30 loop recursions-- ARRAY{1}::create loop am::=c.next!;-- AM_CURSOR::next! typecase am when AM_RAISE_STMT then after_loop_break[c.loops]:=true;-- ARRAY{1}::aset AM_CURSOR::loops when AM_BREAK_STMT then after_loop_break[c.loops]:=true;-- ARRAY{1}::aset AM_CURSOR::loops when AM_ITER_CALL_EXPR then -- we don't hoist iter expressions anyway, so -- there is no need to handle this case specially after_loop_break[c.loops]:=true;-- ARRAY{1}::aset AM_CURSOR::loops when AM_RETURN_STMT then after_loop_break[c.loops]:=true;-- ARRAY{1}::aset AM_CURSOR::loops when AM_LOOP_STMT then after_loop_break[c.loops+1]:=false;-- ARRAY{1}::aset AM_CURSOR::loops INT::plus if prog.move_while and pass <=2 then-- OPT_CONST::prog PROG::move_while INT::is_lt BOOL::not b::=am.body;-- AM_LOOP_STMT::body typecase b when AM_IF_STMT then -- move a first while! or until! out of and to -- the end of the loop if (void(b.if_true) or void(b.if_false)) and has_no_iter(b.test) -- AM_IF_STMT::if_true AM_IF_STMT::if_false OPT_CONST::has_no_iter AM_IF_STMT::test and (void(am.first_while_moved) or SYS::id(am.first_while_moved)/=SYS::id(b)) then-- AM_LOOP_STMT::first_while_moved SYS::id AM_LOOP_STMT::first_while_moved INT::is_eq SYS::id BOOL::not if void(am.first_while_moved) then am.first_while_moved:=b; end;-- AM_LOOP_STMT::first_while_moved AM_LOOP_STMT::first_while_moved br:$AM_STMT; if void(b.if_true) then-- AM_IF_STMT::if_true br:=b.if_false;-- AM_IF_STMT::if_false else br:=b.if_true;-- AM_IF_STMT::if_true end; typecase br when AM_BREAK_STMT then nif::=#AM_IF_STMT(am.source);-- AM_IF_STMT::create AM_LOOP_STMT::source nif.test:=b.test.copy;-- AM_IF_STMT::test AM_IF_STMT::test c.replace_stmt(nif);-- AM_CURSOR::replace_stmt if void(b.if_true) then -- AM_IF_STMT::if_true nif.if_true:=am;-- AM_IF_STMT::if_true else nif.if_false:=am;-- AM_IF_STMT::if_false end; am.next:=void;-- AM_LOOP_STMT::next am.body:=am.body.next;-- AM_LOOP_STMT::body AM_LOOP_STMT::body last::=am.body;-- AM_LOOP_STMT::body if void(last) then am.body:=b;-- AM_LOOP_STMT::body else loop while!(~void(last.next));-- BOOL::not last:=last.next; end; last.next:=b; end; b.next:=void;-- AM_IF_STMT::next prog.stat.incr("O: # of while!/until! moved to the end of the loop");-- OPT_CONST::prog PROG::stat res:=true; if prog.opt_debug then-- OPT_CONST::prog PROG::opt_debug #OUT+"moved a while!/until! iter to the end of the loop\n";-- OUT::create OUT::plus end; else end; end; else end; end; when AM_LOCAL_EXPR then -- we don't want to hoist local variables. when $AM_CONST then -- we don't want to hoist consts either. when AM_GLOBAL_EXPR then -- same is true for global expressions when $AM_EXPR then if c.loops>0 and prog.hoist_const and c.not_in_a_case_in_a_loop and c.not_prefetch_attr and -- AM_CURSOR::loops INT::is_lt OPT_CONST::prog PROG::hoist_const AM_CURSOR::not_in_a_case_in_a_loop AM_CURSOR::not_prefetch_attr ((pass>1 and ~func.is_iter) or ~c.in_iter_init) then-- INT::is_lt AM_ROUT_DEF::is_iter BOOL::not AM_CURSOR::in_iter_init BOOL::not in_conditional::= ~c.not_in_a_conditional_in_loop;-- AM_CURSOR::not_in_a_conditional_in_loop need_safe_attr::=after_loop_break[c.loops] or in_conditional;-- ARRAY{1}::aget AM_CURSOR::loops if (~need_safe_attr or ~prog.void_checks or ~has_attr_expr(am))-- BOOL::not OPT_CONST::prog PROG::void_checks BOOL::not OPT_CONST::has_attr_expr BOOL::not and hoistable(am,c,need_safe_attr,in_conditional) then-- OPT_CONST::hoistable prog.stat.incr("O: # of expressions hoisted");-- OPT_CONST::prog PROG::stat res:=true; if void(am.tp) then se::=#AM_EXPR_STMT(am.source);-- AM_EXPR_STMT::create se.expr:=am;-- AM_EXPR_STMT::expr c.delete_current;-- AM_CURSOR::delete_current if need_safe_attr then make_safe_attr(se); end;-- OPT_CONST::make_safe_attr c.insert_in_loop_init(se);-- AM_CURSOR::insert_in_loop_init if prog.opt_debug then-- OPT_CONST::prog PROG::opt_debug #OUT+"expression stmt hoisted:\n";-- OUT::create OUT::plus AM_OUT::AM_out(am);#OUT+" (need_safe_attr="+need_safe_attr+")\n";-- AM_OUT::AM_out OUT::create OUT::plus OUT::plus OUT::plus end; else e::=c.loop_stmt.hoisted;-- AM_CURSOR::loop_stmt AM_LOOP_STMT::hoisted found_expr::=false; if ~void(e) then-- BOOL::not loop i::=e.ind!;-- FLIST{1}::ind! if am=e[i].expr then-- FLIST{1}::aget EXPR_HOISTED::expr prog.stat.incr("O: # of double hoisted expressions");-- OPT_CONST::prog PROG::stat if prog.opt_debug then-- OPT_CONST::prog PROG::opt_debug #OUT+"double expression stmt hoisted:\n";-- OUT::create OUT::plus AM_OUT::AM_out(am);#OUT+" (need_safe_attr="+need_safe_attr+")\n";-- AM_OUT::AM_out OUT::create OUT::plus OUT::plus OUT::plus end; res:=true; found_expr:=true; if e[i].is_safe and ~need_safe_attr then-- FLIST{1}::aget EXPR_HOISTED::is_safe BOOL::not make_unsafe_attr(e[i].expr);-- OPT_CONST::make_unsafe_attr FLIST{1}::aget EXPR_HOISTED::expr end; c.replace_expr(e[i].local);-- AM_CURSOR::replace_expr FLIST{1}::aget EXPR_HOISTED::local break!; end; end; end; if ~found_expr then-- BOOL::not l::=new_local(func,am.tp);-- OPT_CONST::new_local as::=#AM_ASSIGN_STMT(am.source);-- AM_ASSIGN_STMT::create as.dest:=l;-- AM_ASSIGN_STMT::dest as.src:=am;-- AM_ASSIGN_STMT::src comment::=#AM_COMMENT_STMT(am.source);-- AM_COMMENT_STMT::create comment.comment:="hoisted expression comming from "+am.source.str;-- AM_COMMENT_STMT::comment STR::plus SFILE_ID::str if need_safe_attr then make_safe_attr(am); end;-- OPT_CONST::make_safe_attr c.insert_in_loop_init(comment);-- AM_CURSOR::insert_in_loop_init c.insert_in_loop_init(as);-- AM_CURSOR::insert_in_loop_init c.replace_expr(l);-- AM_CURSOR::replace_expr c.loop_stmt.hoisted:=e.push(#EXPR_HOISTED(am,need_safe_attr,l));-- AM_CURSOR::loop_stmt AM_LOOP_STMT::hoisted FLIST{1}::push EXPR_HOISTED::create if prog.opt_debug then-- OPT_CONST::prog PROG::opt_debug #OUT+"expression hoisted:\n";-- OUT::create OUT::plus AM_OUT::AM_out(am);-- AM_OUT::AM_out #OUT+" (need_safe_attr="+need_safe_attr+")\n"-- OUT::create OUT::plus OUT::plus end;-- OUT::plus end; end; end; end; typecase am when AM_ROUT_CALL_EXPR then -- there coud be a raise in this routine cal. If we are unable to -- know this (because we compile without side effects), we assume -- the worst. after_loop_break[c.loops]:=after_loop_break[c.loops] -- ARRAY{1}::aset AM_CURSOR::loops ARRAY{1}::aget AM_CURSOR::loops or ~c.with_side_effects or (~void(am.fun.get_se_context(prog)) and am.fun.get_se_context(prog).has_raise);-- AM_CURSOR::with_side_effects BOOL::not AM_ROUT_CALL_EXPR::fun SIG::get_se_context OPT_CONST::prog BOOL::not AM_ROUT_CALL_EXPR::fun SIG::get_se_context OPT_CONST::prog SE_CONTEXT::has_raise else end; when AM_ASSIGN_STMT then if c.loops>0 and prog.hoist_const and c.not_in_a_case_in_a_loop and -- AM_CURSOR::loops INT::is_lt OPT_CONST::prog PROG::hoist_const AM_CURSOR::not_in_a_case_in_a_loop ((pass>1 and ~func.is_iter) or ~c.in_iter_init) then-- INT::is_lt AM_ROUT_DEF::is_iter BOOL::not AM_CURSOR::in_iter_init BOOL::not in_conditional::= ~c.not_in_a_conditional_in_loop;-- AM_CURSOR::not_in_a_conditional_in_loop need_safe_attr::=after_loop_break[c.loops] or in_conditional;-- ARRAY{1}::aget AM_CURSOR::loops if (~need_safe_attr or ~prog.void_checks or ~has_attr_expr(am))-- BOOL::not OPT_CONST::prog PROG::void_checks BOOL::not OPT_CONST::has_attr_expr BOOL::not and hoistable_dest(am,c,need_safe_attr,in_conditional)-- OPT_CONST::hoistable_dest and hoistable(am.src,c,need_safe_attr,in_conditional) then-- OPT_CONST::hoistable AM_ASSIGN_STMT::src if need_safe_attr then make_safe_attr(am.src); end;-- OPT_CONST::make_safe_attr AM_ASSIGN_STMT::src if prog.opt_debug then-- OPT_CONST::prog PROG::opt_debug #OUT+"assignment hoisted: (need_safe_attr="+need_safe_attr+")\n";-- OUT::create OUT::plus OUT::plus OUT::plus AM_OUT::AM_one_stmt(am);-- AM_OUT::AM_one_stmt end; c.delete_current;-- AM_CURSOR::delete_current comment::=#AM_COMMENT_STMT(am.source);-- AM_COMMENT_STMT::create AM_ASSIGN_STMT::source comment.comment:="hoisted assignment comming from "+am.source.str;-- AM_COMMENT_STMT::comment STR::plus AM_ASSIGN_STMT::source SFILE_ID::str c.insert_in_loop_init(comment);-- AM_CURSOR::insert_in_loop_init c.insert_in_loop_init(am);-- AM_CURSOR::insert_in_loop_init prog.stat.incr("O: # of assignments hoisted");-- OPT_CONST::prog PROG::stat res:=true; -- else -- if prog.opt_debug then -- #OUT+"assignment NOT hoisted: need_safe_attr="+need_safe_attr+" "; -- #OUT+"prog.void_checks="+prog.void_checks; -- #OUT+" has_attr_expr="+has_attr_expr(am)+"\n"; -- -- #OUT+"hoistable_dest="+hoistable_dest(am,c,need_safe_attr,in_conditional)+ -- -- "hoistable="+hoistable(am.src,c,need_safe_attr,in_conditional)+"\n"; -- AM_OUT::AM_one_stmt(am); -- end; end; end; else end; end; if ~void(c.top) then -- there may be some new statements at the beginning,-- AM_CURSOR::top BOOL::not -- so we have to adjust func.code. tam::=c.top;-- AM_CURSOR::top typecase tam when $AM_STMT then func.code:=tam; end;-- AM_ROUT_DEF::code end; return res; end; end;