From: Georg Bauhaus <rm.plus-bug.tsoh@maps.futureapps.de>
Subject: Re: Problem using Ada.Text_IO.Modular_IO
Date: Sun, 13 Jul 2008 18:03:31 +0200
Date: 2008-07-13T18:03:31+02:00 [thread overview]
Message-ID: <1215965011.20645.42.camel@K72> (raw)
In-Reply-To: <Akcek.225781$SV4.183801@bgtnsc04-news.ops.worldnet.att.net> <4eab7055-df3d-4d56-87da-8248829da1da@26g2000hsk.googlegroups.com> <867127d8-3b21-40dd-bb76-f19cd349b21e@26g2000hsk.googlegroups.com> <4%Pdk.112546$102.54800@bgtnsc05-news.ops.worldnet.att.net> <4878820c$0$27451$9b4e6d93@newsspool4.arcor-online.net> <Akcek.225781$SV4.183801@bgtnsc04-news.ops.worldnet.att.net>
On Sun, 2008-07-13 at 00:51 +0000, anon wrote:
> Plus, when a programmer defines their own type in Ada, Ada adds
> extra set of routines that are not based in hardware checks but software,
> which slows a program down.
I'm not sure there is some real context here. There is no loss
in speed and no cost in terms of additional checks for using
either Unsigned_64 or "mod 2**64". (Or "mod 2**(something smaller)".)
Below is an example to serve as one of many (really unnecessary)
proofs that there is no overhead stemming from user defined types
"mod 2**N". (And no overhead stemming from user defined types
in general---they are there for a reason in this real-time
systems programming language, I should think.)
Hardware will in the end fetch words from memory etc., but what
does this have to do with using a type mod 2**64 instead
of using Unsigned_64? The compiler produces the code, just the
compiler. Will a 64bit compiler use different intrinsic
routines (such as "+") when the arguments are not Unsigned_64
but of type mod 2**64? It does *not* seem to be the case, see
below. No magically different checks either. Turning checks
on/off is in the hands of the compiler operator.
For the code appended, I get not a single difference
in object code when using "mod 2**64" or Unsigned_64.
With or without optimization, neither the representation
nor the instructions differ at all. Not a bit.
Even using a packed array of 64 Booleans gives the very same
code with -O, and a very small difference results with -O0
between the boolean array code and the scalar types code.
I would have expected exactly this to be the case.
Here is the machine code of subprogram Predefined which
is using Unsigned_64 as an "in out" Parameter, then
followed by machine code of subprogram Programmer_Defined
which uses "mod 2**64".
First the case with some optimization.
The Ada subprogram is, basically,
procedure P(Item: in out T) is
begin
Item := not Item;
end P;
where T stands for Unsigned_64 and "mod 2**64", resp.
$ gnatmake -gnata -gnato -gnatwa -O -fno-inline speed.adb
0000000000000000 <speed__predefined.1692>:
0: 48 89 f8 mov %rdi,%rax
3: 48 f7 d0 not %rax
6: c3 retq
7: 90 nop
0000000000000008 <speed__programmer_defined.1700>:
8: 48 89 f8 mov %rdi,%rax
b: 48 f7 d0 not %rax
e: c3 retq
f: 90 nop
No difference. (And no checks.)
Next with no optimization at all:
$ gnatmake -gnata -gnato -gnatwa -O0 -fno-inline speed.adb
00000000000003c6 <speed__programmer_defined.1700>:
3c6: 55 push %rbp
3c7: 48 89 e5 mov %rsp,%rbp
3ca: 48 89 7d f8 mov %rdi,-0x8(%rbp)
3ce: 4c 89 55 f0 mov %r10,-0x10(%rbp)
3d2: 48 f7 55 f8 notq -0x8(%rbp)
3d6: 48 8b 45 f8 mov -0x8(%rbp),%rax
3da: c9 leaveq
3db: c3 retq
00000000000003dc <speed__predefined.1692>:
3dc: 55 push %rbp
3dd: 48 89 e5 mov %rsp,%rbp
3e0: 48 89 7d f8 mov %rdi,-0x8(%rbp)
3e4: 4c 89 55 f0 mov %r10,-0x10(%rbp)
3e8: 48 f7 55 f8 notq -0x8(%rbp)
3ec: 48 8b 45 f8 mov -0x8(%rbp),%rax
3f0: c9 leaveq
3f1: c3 retq
No difference. (And no checks.)
with Interfaces; use Interfaces;
with Ada.Text_IO; use Ada.Text_IO;
procedure Speed2 is
--
-- Case 1:
-- reusing predefined type from Interfaces:
--
procedure Predefined(Item: in out Unsigned_64) is
begin
Item := not Item;
end Predefined;
--
-- Case 2:
-- using a programmer defind modular type:
--
type B_Set is mod 2**64;
procedure Programmer_Defined(Item: in out B_Set) is
begin
Item := not Item;
end Programmer_Defined;
--
-- Case 3:
-- using a different programmer defined type:
--
type Bit_List is array(Positive range <>) of Boolean;
pragma Pack(Bit_List);
subtype B_List is Bit_List(1 .. 64);
procedure Really_Programmer_Defined(Item: in out B_List) is
begin
Item := not Item;
end Really_Programmer_Defined;
--
-- IO of inputs and results
--
package IO_U64 is new Ada.Text_IO.Modular_IO(Unsigned_64);
package IO_B is new Ada.Text_IO.Modular_IO(B_Set);
package IO_L is
-- a fake IO package for hex output of boolean array `B_List`
Default_Width : Ada.Text_IO.Field := Unsigned_64'Width;
Default_Base : Ada.Text_IO.Number_Base := 10;
procedure Put(Item: B_List;
Base: Number_Base := Default_Base;
Width: Field := Default_Width);
end IO_L;
package body IO_L is separate;
begin -- Speed
-- Starting with case 3. The bit values are set for position
-- numbered ranges. These will become bit positions in the other
-- cases.
-- pragma Volatile appears to help prevent Constraint_Error for
-- non-static universal integer in `Value = 16#...#` with current
-- GNAT.
-- case 3:
Packed_Arrays: declare
Value: B_List;
begin
Value := B_List'
(1 .. 10 => True,
11 .. 27 => False,
28 .. 40 => True,
41 .. 42 => False,
43 .. 63 => True,
64 => False);
Put(" As B_List: "); IO_L.Put(Value, Base => 16); New_Line;
Really_Programmer_Defined(Value);
Put(" As B_List: "); IO_L.Put(Value, Base => 16); New_Line;
end Packed_Arrays;
-- case 2:
User_Mod_Types: declare
Value: B_Set;
pragma Volatile(Value);
begin
Value :=
2#1111111111_00000000000000000_1111111111111_00_111111111111111111111_0#;
pragma Assert(Value = 16#FFC0001FFF3FFFFE#);
Put(" As B_Set: "); IO_B.Put(Value, Base => 16); New_Line;
Programmer_Defined(Value);
Put(" As B_Set: "); IO_B.Put(Value, Base => 16); New_Line;
end User_Mod_Types;
-- case 1:
Interface_Types: declare
Value: Unsigned_64;
pragma Volatile(Value);
begin
Value :=
2#1111111111_00000000000000000_1111111111111_00_111111111111111111111_0#;
pragma Assert(Value = 16#FFC0001FFF3FFFFE#);
Put("As Unsigned_64: "); IO_U64.Put(Value, Base => 16); New_Line;
Predefined(Value);
Put("As Unsigned_64: "); IO_U64.Put(Value, Base => 16); New_Line;
end Interface_Types;
end Speed2;
separate(Speed2)
package body IO_L is
Four : constant Positive := 4;
subtype B_List4 is Bit_List(1 .. Four);
function To_Char(Item: B_List4) return Character is
-- Character representing the `Item` as a hex digit
type N8 is range 0 .. 2**Four - 1;
function As_N8(Omit_First: Boolean) return N8 is
-- compute `Item`'s value from bits [1,]2,3,4 independent of
-- bit order
Result: N8;
First_Bit: constant Positive := 1 + Boolean'Pos(Omit_First);
begin
Result := 0;
for K in First_Bit .. Four loop
Result := Result + 2**(Four - K) * Boolean'Pos(Item(K));
end loop;
return Result;
end As_N8;
begin -- To_Char
if Item(1) and then (Item(2) or Item(3)) then
-- hex digit A, B, ...
return Character'Val(Character'Pos('A') +
As_N8(Omit_First => True) - 2);
else
-- decimal digit
return Character'Val(Character'Pos('0') +
As_N8(Omit_First => False));
end if;
end To_Char;
procedure Put(Item: B_List;
Base: Number_Base := Default_Base;
Width: Field := Default_Width)
is
Num_Half_Bytes : constant Positive := B_List'Size / Four;
Result: String(1 .. Num_Half_Bytes);
begin
case Base is
when 16 =>
for J in 0 .. Num_Half_Bytes - 1 loop
Result(J + 1) :=
To_Char(Item((J) * Four + 1 .. (J + 1) * Four));
end loop;
declare
Extra_Spaces: constant Natural :=
Positive'Max(Width - Num_Half_Bytes - 4, 0);
begin
Ada.Text_IO.Put(String'(1 .. Extra_Spaces => ' ')
&"16#" & Result & "#");
end;
when others =>
-- not supported
raise Program_Error;
end case;
end Put;
end IO_L;
next prev parent reply other threads:[~2008-07-13 16:03 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-09 16:52 Problem using Ada.Text_IO.Modular_IO jujosei
2008-07-09 19:03 ` Anh Vo
2008-07-09 19:22 ` Adam Beneschan
2008-07-09 21:50 ` Adam Beneschan
2008-07-10 15:00 ` jujosei
2008-07-10 0:48 ` anon
2008-07-10 1:52 ` Adam Beneschan
2008-07-10 7:25 ` anon
2008-07-10 14:59 ` Adam Beneschan
2008-07-11 0:34 ` anon
2008-07-11 9:49 ` Georg Bauhaus
2008-07-11 10:05 ` christoph.grein
2008-07-11 13:21 ` John McCormick
2008-07-11 12:16 ` anon
2008-07-11 13:26 ` petter_fryklund
2008-07-11 21:10 ` anon
2008-07-12 10:06 ` Georg Bauhaus
2008-07-13 0:51 ` anon
2008-07-13 16:03 ` Georg Bauhaus [this message]
2008-07-14 2:03 ` anon
2008-07-14 13:12 ` Georg Bauhaus
2008-07-16 6:16 ` micronian2
2008-07-16 7:47 ` anon
2008-07-17 16:33 ` micronian2
2008-07-14 16:34 ` micronian2
2008-07-14 17:26 ` Georg Bauhaus
2008-07-16 6:28 ` micronian2
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox