o_iter.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
---------------------------> Sather 1.1 source file <--------------------------
-- this class is included in optimize.sa and cannot be
-- used stand alone
class OPT_ITER
class OPT_ITER is
include OPT_HELPER;
private opt_inlined_iter(func:AM_ROUT_DEF,n:AM_STMT_EXPR,c:AM_CURSOR,
it:AM_ITER_CALL_EXPR,need_safe_attr:BOOL,in_conditional:BOOL) is
-- This function tries to move iter initialization
-- out of the loop
--
-- we search for the first if statement of the form
-- if some_bool_local
-- we search for all other if some_bool_local statements
-- some_bool_local must be a loop constant.
-- The last if statement must have an assignment of the
-- form some_bool_local:=false
-- currently we check only AM_ASSIGN_STMT. AM_PRE, AM_POST and AM_ASSERT_STMT
-- are deleted.
-- we begin by inlining all functions if possible.
-- (this has to be done here, as the code where this
-- iter initializations may be moved to has already been checked
-- for functions to be inlined. Therefor the iter code that is moved
-- will never again be checked for such functions.
cc::=#AM_CURSOR(prog,n.stmts);-- AM_CURSOR::create OPT_ITER::prog AM_STMT_EXPR::stmts
loop
am::=cc.next!; -- AM_CURSOR::next!
typecase am when AM_ROUT_CALL_EXPR then
dummy::=inline_func(func,am,cc);-- OPT_ITER::inline_func
else end;
end;
am::=n.stmts;-- AM_STMT_EXPR::stmts
lbool:AM_LOCAL_EXPR:=void;
move_lbool::=true;
-- search the bool local
loop
while!(~void(am) and void(lbool));-- BOOL::not
typecase am when AM_IF_STMT then
ifx::=am.test;-- AM_IF_STMT::test
typecase ifx when AM_LOCAL_EXPR then
lbool:=ifx;
else end;
else end;
end;
if void(lbool) then
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"could not move out statements, as I did not find the bool local\n";-- OUT::create OUT::plus
end;
return;
end;
if ~c.is_const_in_loop(lbool) then -- AM_CURSOR::is_const_in_loop BOOL::not
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"sorry, but the local bool var is not a loop const: ";-- OUT::create OUT::plus
AM_OUT::AM_out(lbool);#OUT+"\n";-- AM_OUT::AM_out OUT::create OUT::plus
end;
return;
end;
if c.loop_stmt.firsts.index_of(lbool)<0 then-- AM_CURSOR::loop_stmt AM_LOOP_STMT::firsts FLIST{1}::index_of INT::is_lt
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"the local bool constant I found will not be initialized to true at the beginning of the loop\n";-- OUT::create OUT::plus
end;
return;
end;
-- find the first and only ASSIGN_STMT for lbool
-- check that there are no more.
c1::=#AM_CURSOR(prog,n.stmts);-- AM_CURSOR::create OPT_ITER::prog AM_STMT_EXPR::stmts
c1.ignore_pre:=true;-- AM_CURSOR::ignore_pre
c1.ignore_post:=true;-- AM_CURSOR::ignore_post
c1.ignore_assert:=true;-- AM_CURSOR::ignore_assert
found_it::=false;
ignore_next_reference::=true;
loop
d::=c1.next!;-- AM_CURSOR::next!
typecase d when AM_ASSIGN_STMT then
dst::=d.dest;-- AM_ASSIGN_STMT::dest
typecase dst when AM_LOCAL_EXPR then
if dst=lbool then-- AM_LOCAL_EXPR::is_eq
if found_it then
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"found two assignments to the bool local :-(\n";-- OUT::create OUT::plus
end;
return;
else
found_it:=true;
-- there is just one reference to the local var left,
-- namely the one in this assign stmt.
ignore_next_reference:=true;
-- the assignment must be within an if stmt, so its
-- indent must be 1
if c1.indent/=1 then-- AM_CURSOR::indent INT::is_eq BOOL::not
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"indent="+c1.indent+", so assignment is not at the first level of an if stmt.\n";-- OUT::create OUT::plus OUT::plus AM_CURSOR::indent OUT::plus
end;
return ;
end;
s::=c1.get_surr_stmt;-- AM_CURSOR::get_surr_stmt
typecase s when AM_IF_STMT then
t::=s.test;-- AM_IF_STMT::test
typecase t when AM_LOCAL_EXPR then
if t/=lbool then-- AM_LOCAL_EXPR::is_eq BOOL::not
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"wrong test local expr in if stmt.\n";-- OUT::create OUT::plus
end;
return;
end;
else
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"wrong test clause in if stmt.\n";-- OUT::create OUT::plus
end;
return;
end;
tr::=s.if_true;-- AM_IF_STMT::if_true
loop
while!(~void(tr));-- BOOL::not
if SYS::id(tr)=SYS::id(d) then break!; end;-- SYS::id INT::is_eq SYS::id
tr:=tr.next;
end;
if void(tr) then
if prog.opt_debug then -- OPT_ITER::prog PROG::opt_debug
#OUT+"Assignment is not in the true clause of the if stmt\n";-- OUT::create OUT::plus
end;
end;
src::=d.src;-- AM_ASSIGN_STMT::src
typecase src when AM_BOOL_CONST then
if src.val/=false then-- AM_BOOL_CONST::val BOOL::is_eq BOOL::not
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"Assignment is :=true instead of :=false\n";-- OUT::create OUT::plus
end;
return;
end;
else
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"Assignment is not :=true\n";-- OUT::create OUT::plus
end;
return;
end;
else
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"assignment is not within an if stmt\n";-- OUT::create OUT::plus
end;
return;
end;
end;
end;
else end;
when AM_LOCAL_EXPR then
if found_it then -- check that lbool is not used after the
-- assignment lbool:=false;
if ignore_next_reference then
ignore_next_reference:=false;
else
if d=lbool then-- AM_LOCAL_EXPR::is_eq
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"there is a reference to lbool after lbool:=false;\n";-- OUT::create OUT::plus
end;
return;
end;
end;
end;
else end;
end;
-- When we get here, we know the correct bool local, and
-- can proceed to move the statments out of the if
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"it seems that we can move out some statements\n";-- OUT::create OUT::plus
end;
comment::=#AM_COMMENT_STMT(it.source);-- AM_COMMENT_STMT::create AM_ITER_CALL_EXPR::source
comment.comment:="Initialization of inlined iter "+it.fun.str;-- AM_COMMENT_STMT::comment STR::plus AM_ITER_CALL_EXPR::fun SIG::str
c.insert_in_loop_init(comment);-- AM_CURSOR::insert_in_loop_init
pr:$AM_STMT:=void;
am:=n.stmts;-- AM_STMT_EXPR::stmts
inlined::=#AM_CURSOR(prog,n.stmts);-- AM_CURSOR::create OPT_ITER::prog AM_STMT_EXPR::stmts
inlined.ignore_pre:=true;-- AM_CURSOR::ignore_pre
inlined.ignore_post:=true;-- AM_CURSOR::ignore_post
inlined.ignore_assert:=true;-- AM_CURSOR::ignore_assert
inlined.init_next;inlined.next;-- AM_CURSOR::init_next AM_CURSOR::next
loop
while!(~void(am));-- BOOL::not
typecase am
when AM_IF_STMT then
l::=am.test;-- AM_IF_STMT::test
typecase l when AM_LOCAL_EXPR then
if l=lbool then-- AM_LOCAL_EXPR::is_eq
pr:=void;
if ~void(am.if_false) then move_lbool:=false; end;-- AM_IF_STMT::if_false BOOL::not
ifs::=am.if_true;-- AM_IF_STMT::if_true
inlined.next; -- moves to bool local-- AM_CURSOR::next
inlined.next; -- moves to first statement-- AM_CURSOR::next
loop
while!(~void(ifs));-- BOOL::not
nifs::=ifs.next;
p::=ifs;
do_move::=false;
ignore_stmt::=false;
delete_it::=false;
if SYS::id(ifs)/=SYS::id(inlined.cur) then-- SYS::id INT::is_eq SYS::id AM_CURSOR::cur BOOL::not
#OUT+"inlined and ifs disagree about the current statement\n";-- OUT::create OUT::plus
#OUT+"ifs says:\n";-- OUT::create OUT::plus
AM_OUT::AM_out(ifs);-- AM_OUT::AM_out
#OUT+"and inlined is at:\n";-- OUT::create OUT::plus
AM_OUT::AM_out(inlined.cur);-- AM_OUT::AM_out AM_CURSOR::cur
UNIX::exit(-1);-- UNIX::exit
end;
typecase ifs
when AM_ASSIGN_STMT then
if (~need_safe_attr or ~prog.void_checks or ~has_attr_expr(ifs))-- BOOL::not OPT_ITER::prog PROG::void_checks BOOL::not OPT_ITER::has_attr_expr BOOL::not
and hoistable_init_dest(ifs.dest,c,need_safe_attr,in_conditional)-- OPT_ITER::hoistable_init_dest AM_ASSIGN_STMT::dest
and hoistable_init(ifs.src,c,need_safe_attr,in_conditional) -- OPT_ITER::hoistable_init AM_ASSIGN_STMT::src
and inlined.is_not_used_in_func_before_eval_cur_expr(ifs.dest)-- AM_CURSOR::is_not_used_in_func_before_eval_cur_expr AM_ASSIGN_STMT::dest
and inlined.is_const_in_func_before_eval_cur_expr(ifs.src)-- AM_CURSOR::is_const_in_func_before_eval_cur_expr AM_ASSIGN_STMT::src
then
adest::=ifs.dest;-- AM_ASSIGN_STMT::dest
typecase adest when AM_LOCAL_EXPR then
do_move:=true;
else
if ~need_safe_attr then-- BOOL::not
do_move:=true;
end;
end;
if need_safe_attr and do_move then
make_safe_attr(ifs);-- OPT_ITER::make_safe_attr
end;
else
adest::=ifs.dest;-- AM_ASSIGN_STMT::dest
typecase adest when AM_LOCAL_EXPR then
if adest=lbool then-- AM_LOCAL_EXPR::is_eq
ignore_stmt:=true;
end;
else end;
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
if ~hoistable_init_dest(ifs.dest,c,need_safe_attr,in_conditional) then-- OPT_ITER::hoistable_init_dest AM_ASSIGN_STMT::dest BOOL::not
#OUT+"cannot move assign stmt, as it has no hoistable destination\n";-- OUT::create OUT::plus
end;
if ~hoistable_init(ifs.src,c,need_safe_attr,in_conditional) then-- OPT_ITER::hoistable_init AM_ASSIGN_STMT::src BOOL::not
#OUT+"cannot move assign stmt, as it has no hoistable source\n";-- OUT::create OUT::plus
end;
if ~inlined.is_not_used_in_func_before_eval_cur_expr(ifs.dest) then-- AM_CURSOR::is_not_used_in_func_before_eval_cur_expr AM_ASSIGN_STMT::dest BOOL::not
#OUT+"cannot move assign stmt, as dest is used in inlined iter\n";-- OUT::create OUT::plus
end;
if ~inlined.is_const_in_func_before_eval_cur_expr(ifs.src) then-- AM_CURSOR::is_const_in_func_before_eval_cur_expr AM_ASSIGN_STMT::src BOOL::not
#OUT+"cannot move assign stmt, as source is not const in inlined iter\n";-- OUT::create OUT::plus
end;
end;
end;
when AM_PRE_STMT then
if ~prog.pre_checks then delete_it:=true; end;-- OPT_ITER::prog PROG::pre_checks BOOL::not
when AM_POST_STMT then
if ~prog.post_checks then delete_it:=true; end;-- OPT_ITER::prog PROG::post_checks BOOL::not
when AM_ASSERT_STMT then
if ~prog.assert_checks then delete_it:=true; end;-- OPT_ITER::prog PROG::assert_checks BOOL::not
else end; -- typecase
if do_move then
if void(pr) then
am.if_true:=ifs.next;-- AM_IF_STMT::if_true
else
pr.next:=ifs.next;
end;
nifs:=ifs.next;
p:=pr;
ifs.next:=void;
c.insert_in_loop_init(ifs);-- AM_CURSOR::insert_in_loop_init
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"moving the assign stmt to the beginning of the loop:\n";-- OUT::create OUT::plus
AM_OUT::AM_one_stmt(ifs);-- AM_OUT::AM_one_stmt
end;
-- well, we removed the current stmt of inlined, so we have
-- to trick it a bit and set it to the correct stmt. There is
-- just one problem, namely if the next statment is void. in
-- this case we "invent" a new statment;
if void(nifs) then
inlined.cur:=#AM_COMMENT_STMT(void);-- AM_CURSOR::cur AM_COMMENT_STMT::create
else
inlined.cur:=nifs;-- AM_CURSOR::cur
end;
elsif delete_it then
if void(pr) then
am.if_true:=ifs.next;-- AM_IF_STMT::if_true
else
pr.next:=ifs.next;
end;
nifs:=ifs.next;
p:=pr;
ifs.next:=void;
-- well, we removed the current stmt of inlined, so we have
-- to trick it a bit and set it to the correct stmt. There is
-- just one problem, namely if the next statment is void. in
-- this case we "invent" a new statment;
if void(nifs) then
inlined.cur:=#AM_COMMENT_STMT(void);-- AM_CURSOR::cur AM_COMMENT_STMT::create
else
inlined.cur:=nifs;-- AM_CURSOR::cur
end;
elsif ~ignore_stmt then -- BOOL::not
move_lbool:=false;
end;
pr:=p;
ifs:=nifs;
-- if void(ifs) then we move inlined 5 statements below,
-- and if do_move, we already moved it 10 statements above.
if ~void(ifs) and ~do_move and ~delete_it then inlined.next_stmt; end;-- BOOL::not BOOL::not BOOL::not AM_CURSOR::next_stmt
end; -- loop
-- we must be careful to move the inlined cursor over the if_false
-- part of the if statement.
inlined.surr_stmt;-- AM_CURSOR::surr_stmt
inlined.after_if;-- AM_CURSOR::after_if
end; -- if l=lbool
else end; -- AM_LOCAL_EXPR
else end; -- AM_IF_STMT
am:=am.next;
inlined.next_stmt;-- AM_CURSOR::next_stmt
end; -- loop
-- now we have to delete all empty if statements.
-- if move_lbool is true, we can delete them without
-- checking, otherwise we must make sure that if_true and
-- if_false are both void.
pr:=void;
am:=n.stmts;-- AM_STMT_EXPR::stmts
loop
while!(~void(am));-- BOOL::not
amm::=am;
typecase amm
when AM_IF_STMT then
l::=amm.test;-- AM_IF_STMT::test
typecase l when AM_LOCAL_EXPR then
if l=lbool then-- AM_LOCAL_EXPR::is_eq
if move_lbool or (void(amm.if_true) and void(amm.if_false)) then-- AM_IF_STMT::if_true AM_IF_STMT::if_false
prog.stat.incr("O: # if stmts removed");-- OPT_ITER::prog PROG::stat
if void(pr) then
n.stmts:=am.next;-- AM_STMT_EXPR::stmts
am:=n.stmts;-- AM_STMT_EXPR::stmts
else
pr.next:=am.next;
am:=am.next;
end;
else
pr:=am; am:=am.next;
end;
else
pr:=am; am:=am.next;
end;
else
pr:=am; am:=am.next;
end;
else
pr:=am; am:=am.next;
end;
end; -- loop
-- Well, that's it.
end;
private inline_iter(func:AM_ROUT_DEF,am:AM_ITER_CALL_EXPR,c:AM_CURSOR,
do_optimization:BOOL,need_safe_attr:BOOL,in_conditional:BOOL):BOOL is
if ~prog.inline_iters then return false; end;-- OPT_ITER::prog PROG::inline_iters BOOL::not
ok::=false;
if prog.opt_debug then -- OPT_ITER::prog PROG::opt_debug
#OUT+"Trying to inline the iter call "+am.fun.str+":";-- OUT::create OUT::plus OUT::plus AM_ITER_CALL_EXPR::fun SIG::str OUT::plus
end;
n::=prog.inliner.general_inline(func,c.loop_stmt,am);-- OPT_ITER::prog PROG::inliner AM_CURSOR::loop_stmt
if ~SYS::ob_eq(n,am) then-- SYS::ob_eq BOOL::not
prog.stat.incr("O: # of iter calls inlined");-- OPT_ITER::prog PROG::stat
if prog.opt_debug then -- OPT_ITER::prog PROG::opt_debug
#OUT+"done\n";-- OUT::create OUT::plus
end;
if prog.hoist_iter_init and do_optimization then -- OPT_ITER::prog PROG::hoist_iter_init
typecase n when AM_STMT_EXPR then
-- we have to remove the iter, as otherwise
-- side effects from it may interfere with
-- the optimization below. We replace it with a dummy
-- is_void_expr, which is removed later (a noop
-- expr would be better, of course).
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"iter code before optimization:\n";-- OUT::create OUT::plus
AM_OUT::AM_out(n);-- AM_OUT::AM_out
#OUT+"\n";-- OUT::create OUT::plus
end;
c.replace_expr(#AM_IS_VOID_EXPR(void)); -- AM_CURSOR::replace_expr AM_IS_VOID_EXPR::create
opt_inlined_iter(func,n,c,am,need_safe_attr,in_conditional);-- OPT_ITER::opt_inlined_iter
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"iter code after optimization:\n";-- OUT::create OUT::plus
AM_OUT::AM_out(n);-- AM_OUT::AM_out
#OUT+"\n";-- OUT::create OUT::plus
end;
else end; -- we only consider standard inlined iters
end;
c.replace_expr(n); -- insert the optimized version.-- AM_CURSOR::replace_expr
ok:=true;
else
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"no way\n";-- OUT::create OUT::plus
end;
end;
return ok;
end;
work_on_iter(func:AM_ROUT_DEF,am:AM_ITER_CALL_EXPR,c:AM_CURSOR,after_loop_break:ARRAY{BOOL})
is
stmt::=am.init;-- AM_ITER_CALL_EXPR::init
do_optimize::=~func.is_iter and c.not_in_a_case_in_a_loop;-- AM_ROUT_DEF::is_iter BOOL::not AM_CURSOR::not_in_a_case_in_a_loop
need_safe_attr::=false;
has_attr::=false;
in_conditional::= ~c.not_in_a_conditional_in_loop;-- AM_CURSOR::not_in_a_conditional_in_loop
-- if ~in_conditional the iter can use the loop index
am.use_loop_index:=~in_conditional and am.fun.is_builtin and am.fun.builtin_info.use_index;-- AM_ITER_CALL_EXPR::use_loop_index BOOL::not AM_ITER_CALL_EXPR::fun SIG::is_builtin AM_ITER_CALL_EXPR::fun SIG::builtin_info CONFIG_ROUT::use_index
if am.use_loop_index then prog.stat.incr("O: iters using a loop index variable"); end;-- AM_ITER_CALL_EXPR::use_loop_index OPT_ITER::prog PROG::stat
if am.use_loop_index and void(am.lp.loop_index_var) then-- AM_ITER_CALL_EXPR::use_loop_index AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::loop_index_var
prog.stat.incr("O: loops having a loop index variable");-- OPT_ITER::prog PROG::stat
am.lp.loop_index_var:=new_local(func,tp_int);-- AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::loop_index_var OPT_ITER::new_local OPT_ITER::tp_int
as::=#AM_ASSIGN_STMT(am.lp.source);-- AM_ASSIGN_STMT::create AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::source
as.dest:=am.lp.loop_index_var;-- AM_ASSIGN_STMT::dest AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::loop_index_var
as.src:=zero;-- AM_ASSIGN_STMT::src OPT_ITER::zero
comment::=#AM_COMMENT_STMT(am.source);-- AM_COMMENT_STMT::create AM_ITER_CALL_EXPR::source
comment.comment:="loop index variable";-- AM_COMMENT_STMT::comment
c.insert_in_loop_init(comment);-- AM_CURSOR::insert_in_loop_init
c.insert_in_loop_init(as);-- AM_CURSOR::insert_in_loop_init
p::=#AM_ASSIGN_STMT(am.lp.source);-- AM_ASSIGN_STMT::create AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::source
p.dest:=am.lp.loop_index_var;-- AM_ASSIGN_STMT::dest AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::loop_index_var
mi::=#AM_ROUT_CALL_EXPR(2,am.lp.source);-- AM_ROUT_CALL_EXPR::create AM_ITER_CALL_EXPR::lp AM_LOOP_STMT::source
func.calls:=func.calls.push(mi);-- AM_ROUT_DEF::calls AM_ROUT_DEF::calls FLIST{1}::push
mi[0]:=#(p.dest);-- AM_ROUT_CALL_EXPR::aset AM_CALL_ARG::create AM_ASSIGN_STMT::dest
mi[1]:=#(one);-- AM_ROUT_CALL_EXPR::aset AM_CALL_ARG::create OPT_ITER::one
args::=#ARRAY{ARG}(1);-- ARRAY{1}::create
args[0]:=#(tp_int);-- ARRAY{1}::aset ARG::create OPT_ITER::tp_int
mi.fun:=#SIG(tp_int, #ARRAY{$TP}(0),-- AM_ROUT_CALL_EXPR::fun SIG::create OPT_ITER::tp_int ARRAY{1}::create
IDENT_BUILTIN::plus_ident, args, tp_int, true);-- IDENT_BUILTIN::plus_ident OPT_ITER::tp_int
prog.generate_am.output_sig(mi.fun);-- OPT_ITER::prog PROG::generate_am AM_ROUT_CALL_EXPR::fun
p.src:=mi;-- AM_ASSIGN_STMT::src
c.append_to_loop(p);-- AM_CURSOR::append_to_loop
end;
-- check if we can safely move the initialization of the current iter
-- to the beginning of the loop. This assumes that all assignments in the
-- ini field of the iter are to local variables which are only used during
-- the call of the iter and never somewhere else in the loop.
loop while!(~void(stmt) and do_optimize);-- BOOL::not
typecase stmt when AM_ASSIGN_STMT then
if ~c.is_const(stmt.src) then-- AM_CURSOR::is_const AM_ASSIGN_STMT::src BOOL::not
need_safe_attr:=after_loop_break[c.loops] or in_conditional;-- ARRAY{1}::aget AM_CURSOR::loops
do_optimize:=hoistable_init(stmt.src,c,need_safe_attr,in_conditional);-- OPT_ITER::hoistable_init AM_ASSIGN_STMT::src
has_attr:=has_attr_expr(stmt.src);-- OPT_ITER::has_attr_expr AM_ASSIGN_STMT::src
if ~do_optimize and prog.opt_debug then-- BOOL::not OPT_ITER::prog PROG::opt_debug
#OUT+"the following expression is not hoistable: (need_safe_attr="+need_safe_attr+" in_cond="+in_conditional+")\n";-- OUT::create OUT::plus OUT::plus OUT::plus OUT::plus OUT::plus
AM_OUT::AM_out(stmt.src);-- AM_OUT::AM_out AM_ASSIGN_STMT::src
#OUT+"\n";-- OUT::create OUT::plus
end;
end;
else
if prog.opt_debug then-- OPT_ITER::prog PROG::opt_debug
#OUT+"ignoring iter "+am.fun.str+" because its init_stmt has not only AM_ASSIGN_STMT\n";-- OUT::create OUT::plus OUT::plus AM_ITER_CALL_EXPR::fun SIG::str OUT::plus
end;
do_optimize:=false;
end;
stmt:=stmt.next;
end;
if do_optimize and need_safe_attr and has_attr and prog.void_checks then-- OPT_ITER::prog PROG::void_checks
do_optimize:=false;
end;
if do_optimize then
if ~inline_iter(func,am,c,true,need_safe_attr,in_conditional) then-- OPT_ITER::inline_iter BOOL::not
prog.stat.incr("O: # of iters not inlined");-- OPT_ITER::prog PROG::stat
if prog.opt_verbose and ~am.fun.is_builtin then-- OPT_ITER::prog PROG::opt_verbose AM_ITER_CALL_EXPR::fun SIG::is_builtin BOOL::not
#OUT+am.source.str+": INFO: iter "+am.fun.str+" ignored by inliner.\n";-- OUT::create OUT::plus AM_ITER_CALL_EXPR::source SFILE_ID::str OUT::plus OUT::plus AM_ITER_CALL_EXPR::fun SIG::str OUT::plus
end;
if prog.hoist_iter_init then-- OPT_ITER::prog PROG::hoist_iter_init
if need_safe_attr then make_safe_attr(am.init); end;-- OPT_ITER::make_safe_attr AM_ITER_CALL_EXPR::init
move_init_stmts(func,am,c);-- OPT_ITER::move_init_stmts
end;
end;
else
if prog.opt_verbose and ~am.fun.is_builtin then-- OPT_ITER::prog PROG::opt_verbose AM_ITER_CALL_EXPR::fun SIG::is_builtin BOOL::not
#OUT+am.source.str+": INFO: iter "+am.fun.str+" ignored by optimizer.\n";-- OUT::create OUT::plus AM_ITER_CALL_EXPR::source SFILE_ID::str OUT::plus OUT::plus AM_ITER_CALL_EXPR::fun SIG::str OUT::plus
end;
if ~inline_iter(func,am,c,false,false,in_conditional) then-- OPT_ITER::inline_iter BOOL::not
if prog.opt_verbose and ~am.fun.is_builtin then-- OPT_ITER::prog PROG::opt_verbose AM_ITER_CALL_EXPR::fun SIG::is_builtin BOOL::not
#OUT+am.source.str+": INFO: iter "+am.fun.str+" ignored by inliner.\n";-- OUT::create OUT::plus AM_ITER_CALL_EXPR::source SFILE_ID::str OUT::plus OUT::plus AM_ITER_CALL_EXPR::fun SIG::str OUT::plus
end;
prog.stat.incr("O: # of iters not optimized and not inlined");-- OPT_ITER::prog PROG::stat
-- if prog.opt_debug then
-- #OUT+"do_optimize="+do_optimize+" in_conditional="+in_conditional+"\n";
-- #OUT+"code: ";
-- AM_OUT::AM_out(am,0,5);
-- #OUT+"\n";
-- end;
end;
prog.stat.incr("O: # of iters not optimized");-- OPT_ITER::prog PROG::stat
end;
end;
end;