with Instrument;
use Instrument;

-------------------
--  Integer Expressions
-------------------

--  Each test has the same structure.  The global variable, Global, is
--  assigned the value of an expression.  The primaries of the expression
--  are local variables or literals.  For each operator there is a test
--  whose expression involves a single occurrence of that operator.
--  The purpose of these tests is to evaluate the code generated for
--  simple operators.  There are also mixed expression tests that combine
--  a number of operators into more complex expressions.  These tests
--  assess the expression evaluation order and register assignment
--  techniques used by the code generator.

--  Care is taken in these tests to prevent optimizations from having
--  unwanted effects in the noise version of the tests.  The local
--  variables used are assigned initial values using the Let and
--  Ident subprograms provided by the Compare Support package.  These
--  local variables are then used in the test expression.  In the noise
--  version of the test, this use is not present.  Hence there must
--  be some use that is present in both the test and noise versions.
--  This is achieved by placing after the test expression assignment,
--  a sequence of assignments of the local to the global using Let and
--  Ident:
--                Let(Global, Ident(Local));
--  It is possible, however, that the value of Local will be retained
--  in a register when it is used in the test expression and so will not
--  be fetched from memory to make the call to Ident.  In the noise version
--  of the test there is no test expression, so the value is not likely to
--  be in a register.  Hence, after the test expression assignment, there
--  are assignments, using the Let procedure, to each of the local variables
--  used in the test expression.  But if this is not done carefully, another
--  opportunity for optimization is created in the noise version.  In the
--  noise version it is possible to have two calls to Let to assign a value
--  to Local without an intervening use of Local.  This makes the assignment
--  to Local that results from the first call a dead assignment, and it can
--  be eliminated by an optimizing compiler.  In the test version, the
--  assignment is not dead because there is a subsequent use of Local.
--  To prevent this unwanted optimization, the assignment of the test
--  expression and subsequent assignments to the locals are enclosed within
--  a conditional statement.  The condition is always true so the statements
--  are executed.  However, there is no way using standard data flow analysis
--  to deduce this fact.  Consequently, it appears in both versions that the
--  last use of the locals is preceded by one or the other of the two
--  assignments to them.

procedure Imixa1 is

    Zero : constant := 0;
    One : constant := 1;
    Two : constant := 2;

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

    M, N : T;

begin

    Start ("IMIXA1", "Integer Mixed Expressions 01 (control)");
    for I in 1 .. 10000 loop

        Let (Global, Ident (Zero));
        Let (M, Ident (One));
        Let (N, Ident (One));

        if Global = Zero then
            --   Global := (M + N) * (M - N);        -- included in test version
            Let (M, Ident (One));
            Let (N, Ident (One));
        end if;

        Let (Global, Ident (N));
        Let (Global, Ident (M));

    end loop;
    Stop;

end Imixa1;