This is an internal optimization that reduces the number of cases
in which we generate N_Reference nodes. Generally has no effect
on functional behavior, but the following test:

     1. function StrangeRef (A, B : Integer) return Integer is
     2.    X : Integer;
     3. begin
     4.    X := Integer'Max ((if A > 4 then B else 15), B);
     5.    return X;
     6. end StrangeRef;

compiled with -gnatG and -gnatd.u can be used to see that we do properly
optimize this case and avoid generating an N_Reference node which is what
we used to do:

Source recreated from tree for Strangeref (body)

function strangeref (a : integer; b : integer) return integer is
   x : integer;
begin
   R1b : constant integer := (if a > 4 then integer(b) else 15);
   x := (if (R1b) >= b then (R1b) else integer(b));
   return x;
end strangeref;

Previously R1b generated an N_Reference node

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-02-18  Robert Dewar  <de...@adacore.com>

        * exp_attr.adb: Minor reformatting.
        * exp_ch4.ads, exp_ch4.adb (Expand_N_Reference): New procedure.
        * exp_util.adb (Remove_Side_Effects): Add conditional expressions
        as another case where we don't generate N_Reference nodes for
        primitive types.
        * expander.adb (Expand): Add call to Expand_N_Reference.

Index: exp_util.adb
===================================================================
--- exp_util.adb        (revision 207537)
+++ exp_util.adb        (working copy)
@@ -6972,17 +6972,28 @@
       Scope_Suppress.Suppress := (others => True);
 
       --  If it is a scalar type and we need to capture the value, just make
-      --  a copy. Likewise for a function call, an attribute reference, an
-      --  allocator, or an operator. And if we have a volatile reference and
-      --  Name_Req is not set (see comments above for Side_Effect_Free).
+      --  a copy. Likewise for a function call, an attribute reference, a
+      --  conditional expression, an allocator, or an operator. And if we have
+      --  a volatile reference and Name_Req is not set (see comments above for
+      --  Side_Effect_Free).
 
       if Is_Elementary_Type (Exp_Type)
+
+        --  Note: this test is rather mysterious??? Why can't we just test ONLY
+        --  Is_Elementary_Type and be done with it. If we try that approach, we
+        --  get some failures (infinite recursions) from the Duplicate_Subexpr
+        --  call at the end of Checks.Apply_Predicate_Check. To be
+        --  investigated ???
+
         and then (Variable_Ref
-                   or else Nkind_In (Exp, N_Function_Call,
-                                          N_Attribute_Reference,
-                                          N_Allocator)
+                   or else Nkind_In (Exp, N_Attribute_Reference,
+                                          N_Allocator,
+                                          N_Case_Expression,
+                                          N_If_Expression,
+                                          N_Function_Call)
                    or else Nkind (Exp) in N_Op
-                   or else (not Name_Req and then Is_Volatile_Reference (Exp)))
+                   or else (not Name_Req
+                             and then Is_Volatile_Reference (Exp)))
       then
          Def_Id := Make_Temporary (Loc, 'R', Exp);
          Set_Etype (Def_Id, Exp_Type);
@@ -7230,6 +7241,7 @@
          E := Exp;
          if Nkind (E) = N_Explicit_Dereference then
             New_Exp := Relocate_Node (Prefix (E));
+
          else
             E := Relocate_Node (E);
 
Index: exp_attr.adb
===================================================================
--- exp_attr.adb        (revision 207559)
+++ exp_attr.adb        (working copy)
@@ -1132,20 +1132,20 @@
             --  copies from being created when the unchecked conversion
             --  is expanded (which would happen in Remove_Side_Effects
             --  if Expand_N_Unchecked_Conversion were allowed to call
-            --  Force_Evaluation). The copy could violate Ada semantics
-            --  in cases such as an actual that is an out parameter.
-            --  Note that this approach is also used in exp_ch7 for calls
-            --  to controlled type operations to prevent problems with
-            --  actuals wrapped in unchecked conversions.
+            --  Force_Evaluation). The copy could violate Ada semantics in
+            --  cases such as an actual that is an out parameter. Note that
+            --  this approach is also used in exp_ch7 for calls to controlled
+            --  type operations to prevent problems with actuals wrapped in
+            --  unchecked conversions.
 
             if Is_Untagged_Derivation (Etype (Expression (Item))) then
                Set_Assignment_OK (Item);
             end if;
          end if;
 
-         --  The stream operation to call maybe a renaming created by
-         --  an attribute definition clause, and may not be frozen yet.
-         --  Ensure that it has the necessary extra formals.
+         --  The stream operation to call may be a renaming created by an
+         --  attribute definition clause, and may not be frozen yet. Ensure
+         --  that it has the necessary extra formals.
 
          if not Is_Frozen (Pname) then
             Create_Extra_Formals (Pname);
Index: expander.adb
===================================================================
--- expander.adb        (revision 207533)
+++ expander.adb        (working copy)
@@ -411,6 +411,9 @@
                   when N_Record_Representation_Clause =>
                      Expand_N_Record_Representation_Clause (N);
 
+                  when N_Reference =>
+                     Expand_N_Reference (N);
+
                   when N_Requeue_Statement =>
                      Expand_N_Requeue_Statement (N);
 
Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb (revision 207546)
+++ exp_ch4.adb (working copy)
@@ -9225,6 +9225,65 @@
       Analyze_And_Resolve (N, Standard_Boolean);
    end Expand_N_Quantified_Expression;
 
+   ------------------------
+   -- Expand_N_Reference --
+   ------------------------
+
+   --  It is a little unclear why we generate references to expression values,
+   --  but we definitely do! At the very least in Modify_Tree_For_C, we need to
+   --  get rid of such constructs. We do this by expanding:
+
+   --    expression'Reference
+
+   --  into
+
+   --    Tnn : constant typ := expression;
+   --    ...
+   --    Tnn'Reference
+
+   procedure Expand_N_Reference (N : Node_Id) is
+   begin
+      --  No problem if Modify_Tree_For_C not set, the existing back ends will
+      --  correctly handle P'Reference where P is a general expression.
+
+      if not Modify_Tree_For_C then
+         return;
+
+      --  No problem if we have an entity name since we can take its address
+
+      elsif Is_Entity_Name (Prefix (N)) then
+         return;
+
+      --  Can't go copying limited types
+
+      elsif Is_Limited_Record (Etype (Prefix (N)))
+        or else Is_Limited_Composite (Etype (Prefix (N)))
+      then
+         return;
+
+      --  Here is the case where we do the transformation discussed above
+
+      else
+         declare
+            Loc  : constant Source_Ptr := Sloc (N);
+            Expr : constant Node_Id    := Prefix (N);
+            Typ  : constant Entity_Id  := Etype (N);
+            Tnn  : constant Entity_Id  := Make_Temporary (Loc, 'T', Expr);
+         begin
+            Insert_Action (N,
+              Make_Object_Declaration (Loc,
+                Defining_Identifier => Tnn,
+                Constant_Present    => True,
+                Object_Definition   => New_Occurrence_Of (Etype (Expr), Loc),
+                Expression          => Expr));
+            Rewrite (N,
+              Make_Reference (Loc,
+                Prefix => New_Occurrence_Of (Tnn, Loc)));
+            Analyze_And_Resolve (N, Typ);
+         end;
+      end if;
+   end Expand_N_Reference;
+
    ---------------------------------
    -- Expand_N_Selected_Component --
    ---------------------------------
Index: exp_ch4.ads
===================================================================
--- exp_ch4.ads (revision 207533)
+++ exp_ch4.ads (working copy)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -68,6 +68,7 @@
    procedure Expand_N_Or_Else                     (N : Node_Id);
    procedure Expand_N_Qualified_Expression        (N : Node_Id);
    procedure Expand_N_Quantified_Expression       (N : Node_Id);
+   procedure Expand_N_Reference                   (N : Node_Id);
    procedure Expand_N_Selected_Component          (N : Node_Id);
    procedure Expand_N_Slice                       (N : Node_Id);
    procedure Expand_N_Type_Conversion             (N : Node_Id);

Reply via email to