with Instrument;
use Instrument;

----------------------
-- Arithmetic Elimination
----------------------

--  This test evaluates a code  improvement  potential  that  results
--  from   the   reduction   of  computational  operations  when  the
--  opportunity  is  offered  to  eliminate   a   common   arithmetic
--  subexpression.

--  The test procedures contain explicit  redefinitions  of  Global_1
--  and  Global_2.   A  conditional statement is used to perform only
--  the execution of the redefinition for Global_1.  In the optimized
--  test  procedure  the  redefinition  includes the evaluation of an
--  expression that  contains  a  common  subexpression  using  local
--  variables,   whereas  in  the  nonoptimized  test  procedure  the
--  redefinition evaluates an expression  that  does  not  contain  a
--  common subexpression.

--  Because the test procedures are identical except for the branches
--  of  the  conditional  statement, no difference is expected in the
--  space requirements for the two procedures.   The  effect  of  the
--  improved  code  should  be  evident  from  the  difference in the
--  execution time of the two procedures since the elimination of the
--  arithmetic subexpression collapses the expression evaluation to a
--  simple assignment.

--  Camouflaging the conditional expression prevents other unexpected
--  optimizations that would invalidate the benchmark.

procedure Opaea2 is

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

    Local_1 : T := Ident (Init / Init);
    Local_2 : T := Ident (Init / Init);
    Local_3 : T := Ident (Init / Init);

    Global_1 : T;
    Global_2 : T;
    Global_3 : T;
    Global_4 : T;

begin

    Start ("OPAEA2", "Optimization Perf., Arith. Expr. (test)");
    for I in 1 .. 1000 loop

        Let (Global_1, Ident (Init / Init));
        Let (Global_2, Ident (Init / Init));
        Let (Global_3, Ident (Init / Init));
        Let (Global_4, Ident (Init / Init));

        if Ident (Init) = Init then

            Global_1 := T (T ((Local_1 + Local_2) * Global_3) /
                           (Local_1 + Local_2));
            -- included in test version
            --               T(T((Local_1 + Local_3) * Global_4) / (Local_2 + Local_3));
            -- included in control version

        else

            Global_2 := T (T ((Local_1 + Local_3) * Global_4) /
                           (Local_2 + Local_3));
            -- included in test version
            --               T(T((Local_1 + Local_2) * Global_3) / (Local_1 + Local_2));
            -- included in control version

        end if;

        Let (Global_1, Ident (Init / Init));
        Let (Global_2, Ident (Init / Init));
        Let (Global_3, Ident (Init / Init));
        Let (Global_4, Ident (Init / Init));

    end loop;
    Stop;

end Opaea2;