From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,3d62476d9695a42b,start X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!proxad.net!feeder1-2.proxad.net!cleanfeed1-a.proxad.net!nnrp20-1.free.fr!not-for-mail Date: Sat, 17 Oct 2009 22:34:37 +0200 From: Damien Carbonne User-Agent: Thunderbird 2.0.0.23 (X11/20090812) MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Possible optimization bug in GNAT GPL 2009 ? Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <4ada2a5e$0$25098$426a34cc@news.free.fr> Organization: Guest of ProXad - France NNTP-Posting-Date: 17 Oct 2009 22:34:38 MEST NNTP-Posting-Host: 82.247.219.63 X-Trace: 1255811678 news-4.free.fr 25098 82.247.219.63:52777 X-Complaints-To: abuse@proxad.net Xref: g2news2.google.com comp.lang.ada:8717 Date: 2009-10-17T22:34:38+02:00 List-Id: Hi, I have a program that behaves differently depending on optimization level. I managed to reduce it to a relatively small program. I think there is a bug in GNAT, but before sending a report to AdaCore, I would prefer to have other's opinion. Best regards, Damien Carbonne Here are the files: ------------------------------------------------------------------------ -- pack07.ads package Pack07 is pragma Pure; subtype Real is Long_Float; type Min_Max is (Min, Max); type Index3 is range 0 .. 2; type Tuple3 is array (Index3) of Real; type Point3 is new Tuple3; -- subtype Point3 is Tuple3; -- OK when Point3 is a subtype, not a new type type Vector3 is new Tuple3; -- subtype Vector3 is Tuple3; -- OK when Vector3 is a subtype, not a new type type Plane3 is record N : Vector3; D : Real; end record; type Side_Id is (Left, Right, Bottom, Top, Far, Near); type Plane_Array is array (Side_Id) of Plane3; type Frustum3 is record Planes : Plane_Array; end record; type Corner_Array is array (Min_Max) of Point3; type AABox3 is record Corners : Corner_Array; end record; type Culling_State is (Outside, Intersect, Inside); function Culling (Frustum : Frustum3; Box : AABox3) return Culling_State; end Pack07; ------------------------------------------------------------------------ -- pack07.adb package body Pack07 is function Dot (Left : Vector3; Right : Vector3) return Real; --------- -- Dot -- --------- function Dot (Left : Vector3; Right : Vector3) return Real is begin return Left (0) * Right (0) + Left (1) * Right (1) + Left (2) * Right (2); end Dot; ------------- -- Culling -- ------------- function Culling (Frustum : Frustum3; Box : AABox3) return Culling_State is PMin : Point3; PMax : Point3; Result : Culling_State := Inside; begin for Side in Side_Id loop for Index in Index3 loop if Frustum.Planes (Side).N (Index) >= 0.0 then PMin (Index) := Box.Corners(Min)(Index); PMax (Index) := Box.Corners(Max)(Index); else PMin (Index) := Box.Corners(Max)(Index); PMax (Index) := Box.Corners(Min)(Index); end if; end loop; if Dot (Frustum.Planes (Side).N, Vector3 (PMax)) + Frustum.Planes (Side).D < 0.0 then return Outside; elsif Dot (Frustum.Planes (Side).N, Vector3 (PMin)) + Frustum.Planes (Side).D <= 0.0 then Result := Intersect; end if; end loop; return Result; end Culling; end Pack07; ------------------------------------------------------------------------ -- main07.adb with Ada.Text_IO; with Pack07; use Pack07; procedure Main07 is Frustum : Frustum3; K1 : constant := 7.07106781186547E-01; K2 : constant := 1.76776695296637E+00; Num_X : constant := 2; Step : constant := 2.0; Size : constant := Step / 4.0; X1, X2 : Real; Boxes : array (-Num_X .. Num_X) of AABox3; States : array (-Num_X .. Num_X) of Culling_State; Expected_States : constant array (-Num_X .. Num_X) of Culling_State := (Outside, Intersect, Inside, Intersect, Outside); begin Frustum.Planes (Left) := (( K1, 0.0, -K1), K2); Frustum.Planes (Right) := ((-K1, 0.0, -K1), K2); Frustum.Planes (Bottom) := ((0.0, K1, -K1), K2); Frustum.Planes (Top) := ((0.0, -K1, -K1), K2); Frustum.Planes (Far) := ((0.0, 0.0, 1.0), 7.5); Frustum.Planes (Near) := ((0.0, 0.0, -1.0), 1.5); for X in -Num_X .. Num_X loop X1 := Real (X) * Step - Size; X2 := Real (X) * Step + Size; Boxes (X) := (Corners => (Point3'(X1, -Size, -Size), Point3'(X2, Size, Size))); States (X) := Culling (Frustum, Boxes (X)); end loop; Ada.Text_IO.Put_Line ("OK/KO: Expected Found"); for X in Boxes'Range (1) loop if Culling_State'Image (Expected_States (X)) /= Culling_State'Image (States (X)) then Ada.Text_IO.Put ("KO : "); else Ada.Text_IO.Put ("OK : "); end if; Ada.Text_IO.Put (Culling_State'Image (Expected_States (X))); Ada.Text_IO.Set_Col (20); Ada.Text_IO.Put (Culling_State'Image (States (X))); Ada.Text_IO.New_Line; end loop; end Main07; -- This program compiles and links correctly on Linux box, with GNAT GPL 2009. -- However, its execution differs depending on compilation options. -- 1) When compiled with BUILD = debug ("-O0"), -- the output is: -- OK/KO: Expected Found -- OK : OUTSIDE OUTSIDE -- OK : INTERSECT INTERSECT -- OK : INSIDE INSIDE -- OK : INTERSECT INTERSECT -- OK : OUTSIDE OUTSIDE -- -- 2) When compiled with BUILD = release ("-gnatn", "-funroll-loops", "-O2"), -- the output is: -- OK/KO: Expected Found -- KO : OUTSIDE INTERSECT -- KO : INTERSECT OUTSIDE -- KO : INSIDE OUTSIDE -- KO : INTERSECT OUTSIDE -- OK : OUTSIDE OUTSIDE -- -- By changing certain declarations in Pack07, everything works as expected in -- release mode. -- The change may be: -- "type Point3 is new Tuple3" -> "subtype Point3 is Tuple3" -- or: -- "type Vector3 is new Tuple3" -> "subtype Vector3 is Tuple3" -- -- Other modifications are possible to obtain the expected result. -- -- This looks like a compiler bug to me. But I may be wrong. ------------------------------------------------------------------------ -- bug07.gpr project Bug07 is type Build_Type is ("debug", "release"); Build : Build_Type := External ("BUILD", "debug"); for Source_Dirs use ("src"); for Object_Dir use "obj/" & Build; for Main use ("main07.adb"); package Compiler is case Build is when "release" => for Default_Switches ("ada") use ( "-gnatn", "-funroll-loops", "-O2" ); when "debug" => for Default_Switches ("ada") use ( "-O0" ); end case; end Compiler; end Bug07; ------------------------------------------------------------------------