with Instrument;
use Instrument;

-------------
-- Function Call
-------------

--  This test evaluates the code improvement potential  that  results
--  from  eliminating  context  operations  when  the  opportunity is
--  offered to relocate a function call outside the region of code of
--  a loop body.

--  The two test procedures contain a single  loop  that  encloses  a
--  camouflaged  redefinition  of  a  local  variable, Local_1.  Both
--  redefinitions require  the  evaluation  of  a  function  that  is
--  defined  within  the  test  procedures.   This  function  has  no
--  side-effects and cannot be expanded in-line.  When  the  function
--  is  called  in the optimized test procedure with a loop invariant
--  parameter  the  function  acts  as  a  loop  invariant.   In  the
--  nonoptimized  test  procedure  the parameter used in the function
--  call is not a loop invariant.

--  Consequently, the optimization is evidenced by  a  difference  in
--  the  execution times of the two test procedures since the context
--  operations for the function call are relocated outside the loop.

--  A camouflaged redefinition of Local_1 is  used  in  the  loop  to
--  ensure  that  only  the  function  call  can  be  relocated.  The
--  camouflaged redefinition of Global_1 using Local_1  prevents  the
--  use   of  unexpected  optimizations  that  would  invalidate  the
--  benchmark.

procedure Lofca2 is

    package New_Procs is new Procs (Integer);
    use New_Procs;

    Local_1, Local_2 : T := Ident (Init);

    function Function_1 (Input : T) return T is

    begin

        if Input = Init then
            return Input;
        end if;
        return Function_1 (Init);

    end Function_1;

begin

    Start ("LOFCA2", "Loop Optimization, Function Call (test)");
    for I in 1 .. 1000 loop

        Let (Global, Ident (Init));

        for J in Ident (T'Val (1)) .. Ident (T'Val (10)) loop

            -----optimize-----
            Let (Local_1,
                 Ident (Function_1 (Local_2)));  -- included in test version
            --     Let(Local_1, Ident(Function_1(Local_1)));  -- included in control version

        end loop;

        Let (Global, Ident (Local_1));

        Let (Global, Ident (Init));

    end loop;
    Stop;

end Lofca2;