Dhrystone Benchmark (for Ada) request
rmb at omepd.UUCP
rmb at omepd.UUCP
Sat Oct 4 02:19:45 AEST 1986
Here is the source for the Ada version of the Dhrystone benchmark, as
originally posted to the net by Reinhold Weicker.
**************************** <cut here> ***********************************
------------------------------------------------------------------------------
-- --
-- "DHRYSTONE" Benchmark Program --
-- ----------------------------- --
-- --
-- Version: ADA / 1 (Reference version, all parts in one file) --
-- --
-- File: dhry-ref-all.a --
-- --
-- Date: Oct. 1984 --
-- --
-- Author: Reinhold P. Weicker --
-- --
------------------------------------------------------------------------------
-- --
-- The following program contains statements of a high level programming --
-- language (here: Ada) in a distribution considered representative: --
-- --
-- assignments 53 % --
-- control statements 32 % --
-- procedure, function calls 15 % --
-- --
-- 100 statements are dynamically executed. The program is balanced with --
-- respect to the three aspects: --
-- --
-- - statement type --
-- - operand type (for simple data types) --
-- - operand access --
-- operand global, local, parameter, or constant. --
-- --
-- The combination of these three aspects is balanced only approximately. --
-- --
-- 1. Statement Type: --
-- ----------------- number (= percentage) --
-- --
-- V1 := V2 10 --
-- V := Constant 12 --
-- (incl. V1 := F(..) --
-- Assignment, 7 --
-- with array element --
-- Assignment, 6 --
-- with record component --
-- -- --
-- 35 35 --
-- --
-- X := Y +|-|and|or Z 5 --
-- X := Y +|-|"=" Constant 6 --
-- X := X +|- 1 3 --
-- X := Y *|/ Z 2 --
-- X := Expression, 1 --
-- two operators --
-- X := Expression, 1 --
-- three operators --
-- -- --
-- 18 18 --
-- --
-- if .... then .... 14 --
-- with "else" 7 --
-- without "else" 7 --
-- executed 3 --
-- not executed 4 --
-- for ... loop 6 | counted every time --
-- while ... loop 4 | the loop condition --
-- loop .... exit 1 | is evaluated --
-- case ... end case 1 --
-- return 5 --
-- rename 1 --
-- -- --
-- 32 32 --
-- --
-- P (...) proced. call 10 --
-- same package 5 --
-- other package 5 --
-- --
-- X := F (...) --
-- function call 5 --
-- same package 2 --
-- other package 3 --
-- -- --
-- 15 15 --
-- --- --
-- 100 --
-- --
-- 22 of the 58 assignments have a variable of a constrained --
-- (sub-)type as their destination. In general, discriminant checks --
-- will be necessary in these cases; however, the compiler may --
-- optimize out some of these checks. --
-- --
-- The average number of parameters in procedure or function calls --
-- is 1.80 (not counting the function values as implicit parameters). --
-- --
-- --
-- 2. Operators --
-- ------------ --
-- number approximate --
-- percentage --
-- --
-- Arithmetic 27 52.9 --
-- --
-- + 16 31.4 --
-- - 7 13.7 --
-- * 3 5.9 --
-- / 1 2.0 --
-- --
-- Comparison 20 39.2 --
-- --
-- = 9 17.6 --
-- /= 4 7.8 --
-- > 1 2.0 --
-- < 3 5.9 --
-- >= 1 2.0 --
-- <= 2 3.9 --
-- --
-- Logic 4 7.8 --
-- --
-- AND 1 2.0 --
-- OR 1 2.0 --
-- NOT 2 3.9 --
-- --
-- -- ----- --
-- 51 99.9 --
-- --
-- --
-- 3. Operand Type (counted once per operand reference): --
-- --------------- --
-- number approximate --
-- percentage --
-- --
-- Integer 131 54.4 % --
-- Character 47 19.5 % --
-- Enumeration 31 12.4 % --
-- Boolean 11 5.0 % --
-- Pointer 12 4.6 % --
-- String30 6 2.5 % --
-- Array 2 0.8 % --
-- Record 2 0.8 % --
-- --- ------- --
-- 241 100.0 % --
-- --
-- When there is an access path leading to the final operand (e.g. a record--
-- component), only the final data type on the access path is counted. --
-- --
-- There are 16 accesses to components of a record, 9 of them go to --
-- a component in a variant part. For some of these accesses, the --
-- compiler may suppress generation of code checking the tag field --
-- during optimization. --
-- --
-- --
-- 3. Operand Locality: --
-- ------------------- --
-- --
-- local variable 117 48.5 % --
-- global variable 19 7.9 % --
-- same package 18 11.2 % --
-- other package 1 0.4 % --
-- parameter 45 18.7 % --
-- in 27 11.2 % --
-- inout 12 5.0 % --
-- out 6 2.5 % --
-- function result 5 2.1 % --
-- constant 55 22.8 % --
-- --- ------- --
-- 243 100.0 % --
-- --
-- --
-- There may be cases where a highly optimizing compiler may recognize --
-- unnecessary statements and may not generate code for them. --
-- --
-- There has been no explicit effort to account for the effects of a --
-- cache, or to balance the use of long or short displacements for code or --
-- data. --
-- --
-- The program does not compute anything meaningful, but it is --
-- syntactically and semantically correct. All variables have a value --
-- assigned to them before they are used as a source operand. --
-- --
------------------------------------------------------------------------------
-- --
-- The "Dhrystone" program consists of six library units in the sense of --
-- Ada: Two packages (Pack_1 and Pack_2) consisting of both specification --
-- and body, one package (Global_Def) with specification only, and one --
-- procedure (Main). The package structure is intended since this is the --
-- natural ways for programming in Ada, and there can be systems where --
-- calls and data accesses across package boundaries have execution --
-- times different from those within a package. --
-- In addition, the execution time may depend upon the way the program --
-- is compiled and executed; there are two possible ways: --
-- (1) the six units are compiled separately and linked together later, --
-- (2) the six units are submitted to the compiler in one source file. --
-- --
-- For many Ada systems there will be no difference in execution time, --
-- as far as the two compilation models are concerned. --
-- However, for some machines there may be a difference since different --
-- representations may be used for addresses (16 bit or 32 bit), depending --
-- on the compilation model used. --
-- --
-- If there is a difference in execution time, the times for both models --
-- should be measured; model (1) is the one that corresponds more to actual--
-- software development. Ada was explicitly designed for large software --
-- projects that use separate compilation. --
-- --
-- This file contains the "reference" version of Dhrystone/Ada (i.e. no --
-- statement for measurement are included), with the whole program in --
-- one file. For a version with separate source files for all library --
-- units, see the files dhry-ref-pt1.ada, ..., dhry-ref-pt6.ada. --
-- --
------------------------------------------------------------------------------
package Global_Def is
------------------
-- Global type definitions
type Enumeration is (Ident_1, Ident_2, Ident_3, Ident_4, Ident_5);
subtype One_To_Thirty is integer range 1..30;
subtype One_To_Fifty is integer range 1..50;
subtype Capital_Letter is character range 'A'..'Z';
type String_30 is array (One_To_Thirty) of character;
pragma Pack (String_30);
type Array_1_Dim_Integer is array (One_To_Fifty) of integer;
type Array_2_Dim_Integer is array (One_To_Fifty,
One_To_Fifty) of integer;
type Record_Type (Discr: Enumeration := Ident_1);
type Record_Pointer is access Record_Type;
type Record_Type (Discr: Enumeration := Ident_1) is
record
Pointer_Comp: Record_Pointer;
case Discr is
when Ident_1 => -- only this variant is used,
-- but in some cases discriminant
-- checks are necessary
Enum_Comp: Enumeration;
Int_Comp: One_To_Fifty;
String_Comp: String_30;
when Ident_2 =>
Enum_Comp_2: Enumeration;
String_Comp_2: String_30;
when others =>
Char_Comp_1,
Char_Comp_2: character;
end case;
end record;
end Global_Def;
with Global_Def;
use Global_Def;
package Pack_1 is
--------------
procedure Proc_0;
procedure Proc_1 (Pointer_Par_In: in Record_Pointer);
procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty);
procedure Proc_3 (Pointer_Par_Out: out Record_Pointer);
Int_Glob: integer;
end Pack_1;
with Global_Def;
use Global_Def;
package Pack_2 is
--------------
procedure Proc_6 (Enum_Par_In: in Enumeration;
Enum_Par_Out: out Enumeration);
procedure Proc_7 (Int_Par_In_1,
Int_Par_In_2: in One_To_Fifty;
Int_Par_Out: out One_To_Fifty);
procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer;
Array_Par_In_Out_2: in out Array_2_Dim_Integer;
Int_Par_In_1,
Int_Par_In_2: in integer);
function Func_1 (Char_Par_In_1,
Char_Par_In_2: in Capital_Letter)
return Enumeration;
function Func_2 (String_Par_In_1,
String_Par_In_2: in String_30)
return boolean;
end Pack_2;
with Global_Def, Pack_1;
use Global_Def;
procedure Main is
--------------
begin
Pack_1.Proc_0; -- Proc_0 is actually the main program, but it is part
-- of a package, and a program within a package can
-- not be designated as the main program for execution.
-- Therefore Proc_0 is activated by a call from "Main".
end Main;
with Global_Def, Pack_2;
use Global_Def;
package body Pack_1 is
-------------------
Bool_Glob: boolean;
Char_Glob_1,
Char_Glob_2: character;
Array_Glob_1: Array_1_Dim_Integer;
Array_Glob_2: Array_2_Dim_Integer;
Pointer_Glob,
Pointer_Glob_Next: Record_Pointer;
procedure Proc_4;
procedure Proc_5;
procedure Proc_0
is
Int_Loc_1,
Int_Loc_2,
Int_Loc_3: One_To_Fifty;
Char_Loc: character;
Enum_Loc: Enumeration;
String_Loc_1,
String_Loc_2: String_30;
begin
-- Initializations
Pack_1.Pointer_Glob_Next := new Record_Type;
Pack_1.Pointer_Glob := new Record_Type
'(
Pointer_Comp => Pack_1.Pointer_Glob_Next,
Discr => Ident_1,
Enum_Comp => Ident_3,
Int_Comp => 40,
String_Comp => "DHRYSTONE PROGRAM, SOME STRING"
);
String_Loc_1 := "DHRYSTONE PROGRAM, 1'ST STRING";
-----------------
-- Start timer --
-----------------
Proc_5;
Proc_4;
-- Char_Glob_1 = 'A', Char_Glob_2 = 'B', Bool_Glob = false
Int_Loc_1 := 2;
Int_Loc_2 := 3;
String_Loc_2 := "DHRYSTONE PROGRAM, 2'ND STRING";
Enum_Loc := Ident_2;
Bool_Glob := not Pack_2.Func_2 (String_Loc_1, String_Loc_2);
-- Bool_Glob = true
while Int_Loc_1 < Int_Loc_2 loop -- loop body executed once
Int_Loc_3 := 5 * Int_Loc_1 - Int_Loc_2;
-- Int_Loc_3 = 7
Pack_2.Proc_7 (Int_Loc_1, Int_Loc_2, Int_Loc_3);
-- Int_Loc_3 = 7
Int_Loc_1 := Int_Loc_1 + 1;
end loop;
-- Int_Loc_1 = 3
Pack_2.Proc_8 (Array_Glob_1, Array_Glob_2, Int_Loc_1, Int_Loc_3);
-- Int_Glob = 5
Proc_1 (Pointer_Glob);
for Char_Index in 'A' .. Char_Glob_2 loop -- loop body executed twice
if Enum_Loc = Pack_2.Func_1 (Char_Index, 'C')
then -- not executed
Pack_2.Proc_6 (Ident_1, Enum_Loc);
end if;
end loop;
-- Enum_Loc = Ident_1
-- Int_Loc_1 = 3, Int_Loc_2 = 3, Int_Loc_3 = 7
Int_Loc_3 := Int_Loc_2 * Int_Loc_1;
Int_Loc_2 := Int_Loc_3 / Int_Loc_1;
Int_Loc_2 := 7 * (Int_Loc_3 - Int_Loc_2) - Int_Loc_1;
Proc_2 (Int_Loc_1);
----------------
-- Stop timer --
----------------
end Proc_0;
procedure Proc_1 (Pointer_Par_In: in Record_Pointer)
is -- executed once
Next_Record: Record_Type
renames Pointer_Par_In.Pointer_Comp.all; -- = Pointer_Glob_Next.all
begin
Next_Record := Pointer_Glob.all;
Pointer_Par_In.Int_Comp := 5;
Next_Record.Int_Comp := Pointer_Par_In.Int_Comp;
Next_Record.Pointer_Comp := Pointer_Par_In.Pointer_Comp;
Proc_3 (Next_Record.Pointer_Comp);
-- Next_Record.Pointer_Comp = Pointer_Glob.Pointer_Comp = Pointer_Glob_Next
if Next_Record.Discr = Ident_1
then -- executed
Next_Record.Int_Comp := 6;
Pack_2.Proc_6 (Pointer_Par_In.Enum_Comp, Next_Record.Enum_Comp);
Next_Record.Pointer_Comp := Pointer_Glob.Pointer_Comp;
Pack_2.Proc_7 (Next_Record.Int_Comp, 10, Next_Record.Int_Comp);
else -- not executed
Pointer_Par_In.all := Next_Record;
end if;
end Proc_1;
procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty)
is -- executed once
-- In_Par_In_Out = 3, becomes 7
Int_Loc: One_To_Fifty;
Enum_Loc: Enumeration;
begin
Int_Loc := Int_Par_In_Out + 10;
loop -- executed once
if Char_Glob_1 = 'A'
then -- executed
Int_Loc := Int_Loc - 1;
Int_Par_In_Out := Int_Loc - Int_Glob;
Enum_Loc := Ident_1;
end if;
exit when Enum_Loc = Ident_1; -- true
end loop;
end Proc_2;
procedure Proc_3 (Pointer_Par_Out: out Record_Pointer)
is -- executed once
-- Pointer_Par_Out becomes Pointer_Glob
begin
if Pointer_Glob /= null
then -- executed
Pointer_Par_Out := Pointer_Glob.Pointer_Comp;
else -- not executed
Int_Glob := 100;
end if;
Pack_2.Proc_7 (10, Int_Glob, Pointer_Glob.Int_Comp);
end Proc_3;
procedure Proc_4 -- without parameters
is -- executed once
Bool_Loc: boolean;
begin
Bool_Loc := Char_Glob_1 = 'A';
Bool_Loc := Bool_Loc or Bool_Glob;
Char_Glob_2 := 'B';
end Proc_4;
procedure Proc_5 -- without parameters
is -- executed once
begin
Char_Glob_1 := 'A';
Bool_Glob := false;
end Proc_5;
end Pack_1;
with Global_Def, Pack_1;
use Global_Def;
package body Pack_2 is
-------------------
function Func_3 (Enum_Par_In: in Enumeration) return boolean;
-- forward declaration
procedure Proc_6 (Enum_Par_In: in Enumeration;
Enum_Par_Out: out Enumeration)
is -- executed once
-- Enum_Par_In = Ident_3, Enum_Par_Out becomes Ident_2
begin
Enum_Par_Out := Enum_Par_In;
if not Func_3 (Enum_Par_In)
then -- not executed
Enum_Par_Out := Ident_4;
end if;
case Enum_Par_In is
when Ident_1 => Enum_Par_Out := Ident_1;
when Ident_2 => if Pack_1.Int_Glob > 100
then Enum_Par_Out := Ident_1;
else Enum_Par_Out := Ident_4;
end if;
when Ident_3 => Enum_Par_Out := Ident_2; -- executed
when Ident_4 => null;
when Ident_5 => Enum_Par_Out := Ident_3;
end case;
end Proc_6;
procedure Proc_7 (Int_Par_In_1,
Int_Par_In_2: in One_To_Fifty;
Int_Par_Out: out One_To_Fifty)
is -- executed three times
-- first call: Int_Par_In_1 = 2, Int_Par_In_2 = 3,
-- Int_Par_Out becomes 7
-- second call: Int_Par_In_1 = 6, Int_Par_In_2 = 10,
-- Int_Par_Out becomes 18
-- third call: Int_Par_In_1 = 10, Int_Par_In_2 = 5,
-- Int_Par_Out becomes 17
Int_Loc: One_To_Fifty;
begin
Int_Loc := Int_Par_In_1 + 2;
Int_Par_Out := Int_Par_In_2 + Int_Loc;
end Proc_7;
procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer;
Array_Par_In_Out_2: in out Array_2_Dim_Integer;
Int_Par_In_1,
Int_Par_In_2: in integer)
is -- executed once
-- Int_Par_In_1 = 3
-- Int_Par_In_2 = 7
Int_Loc: One_To_Fifty;
begin
Int_Loc := Int_Par_In_1 + 5;
Array_Par_In_Out_1 (Int_Loc) := Int_Par_In_2;
Array_Par_In_Out_1 (Int_Loc+1) :=
Array_Par_In_Out_1 (Int_Loc);
Array_Par_In_Out_1 (Int_Loc+30) := Int_Loc;
for Int_Index in Int_Loc .. Int_Loc+1 loop -- loop body executed twice
Array_Par_In_Out_2 (Int_Loc, Int_Index) := Int_Loc;
end loop;
Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) :=
Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) + 1;
Array_Par_In_Out_2 (Int_Loc+20, Int_Loc) :=
Array_Par_In_Out_1 (Int_Loc);
Pack_1.Int_Glob := 5;
end Proc_8;
function Func_1 (Char_Par_In_1,
Char_Par_In_2: in Capital_Letter)
return Enumeration
is -- executed three times, returns Ident_1 each time
-- first call: Char_Par_In_1 = 'H', Char_Par_In_2 = 'R'
-- second call: Char_Par_In_1 = 'A', Char_Par_In_2 = 'C'
-- third call: Char_Par_In_1 = 'B', Char_Par_In_2 = 'C'
Char_Loc_1, Char_Loc_2: Capital_Letter;
begin
Char_Loc_1 := Char_Par_In_1;
Char_Loc_2 := Char_Loc_1;
if Char_Loc_2 /= Char_Par_In_2
then -- executed
return Ident_1;
else -- not executed
return Ident_2;
end if;
end Func_1;
function Func_2 (String_Par_In_1,
String_Par_In_2: in String_30) return boolean
is -- executed once, returns false
-- String_Par_In_1 = "DHRYSTONE PROGRAM, 1'ST STRING"
-- String_Par_In_2 = "DHRYSTONE PROGRAM, 2'ND STRING"
Int_Loc: One_To_Thirty;
Char_Loc: Capital_Letter;
begin
Int_Loc := 2;
while Int_Loc <= 2 loop -- loop body executed once
if Func_1 (String_Par_In_1(Int_Loc),
String_Par_In_2(Int_Loc+1)) = Ident_1
then -- executed
Char_Loc := 'A';
Int_Loc := Int_Loc + 1;
end if;
end loop;
if Char_Loc >= 'W' and Char_Loc < 'Z'
then -- not executed
Int_Loc := 7;
end if;
if Char_Loc = 'X'
then -- not executed
return true;
else -- executed
if String_Par_In_1 > String_Par_In_2
then -- not executed
Int_Loc := Int_Loc + 7;
return true;
else -- executed
return false;
end if;
end if;
end Func_2;
function Func_3 (Enum_Par_In: in Enumeration) return boolean
is -- executed once, returns true
-- Enum_Par_In = Ident_3
Enum_Loc: Enumeration;
begin
Enum_Loc := Enum_Par_In;
if Enum_Loc = Ident_3
then -- executed
return true;
end if;
end Func_3;
end Pack_2;
More information about the Comp.sources.unix
mailing list