Browse Source

* load all complex loads of parameters that are needed multiple times
to a temp to prevent calling functions twice

peter 20 years ago
parent
commit
521b7cfa3b
1 changed files with 47 additions and 16 deletions
  1. 47 16
      compiler/ncal.pas

+ 47 - 16
compiler/ncal.pas

@@ -221,28 +221,35 @@ type
 
 
 
 
     procedure maybe_load_para_in_temp(var p:tnode);
     procedure maybe_load_para_in_temp(var p:tnode);
+
+        function is_simple_node(hp:tnode):boolean;
+        begin
+          is_simple_node:=(hp.nodetype in [typen,loadvmtaddrn,loadn,arrayconstructorn]);
+        end;
+
       var
       var
-        hp    : tnode;
+        hp,
+        loadp,
+        refp  : tnode;
+        htype : ttype;
         ptemp : ttempcreatenode;
         ptemp : ttempcreatenode;
+        usederef : boolean;
         newinitstatement,
         newinitstatement,
         newdonestatement : tstatementnode;
         newdonestatement : tstatementnode;
       begin
       begin
         if not assigned(aktcallnode) then
         if not assigned(aktcallnode) then
           internalerror(200410121);
           internalerror(200410121);
 
 
+        { Load all complex loads into a temp to prevent
+          double calls to a function. We can't simply check for a hp.nodetype=calln
+           }
         hp:=p;
         hp:=p;
         while assigned(hp) and
         while assigned(hp) and
-              (hp.nodetype=typeconvn) do
+              (hp.nodetype=typeconvn) and
+              (ttypeconvnode(hp).convtype=tc_equal) do
           hp:=tunarynode(hp).left;
           hp:=tunarynode(hp).left;
         if assigned(hp) and
         if assigned(hp) and
-           (
-            { call result must always be loaded in temp to prevent
-              double creation }
-            (hp.nodetype=calln)
-            { Also optimize also complex loads }
-{$warning Complex loads can also be optimized}
-//            or not(hp.nodetype in [typen,loadvmtaddrn,loadn])
-           )  then
+           not is_simple_node(hp) then
           begin
           begin
             if not assigned(aktcallnode.methodpointerinit) then
             if not assigned(aktcallnode.methodpointerinit) then
               begin
               begin
@@ -255,17 +262,35 @@ type
                 newdonestatement:=laststatement(aktcallnode.methodpointerdone);
                 newdonestatement:=laststatement(aktcallnode.methodpointerdone);
               end;
               end;
             { temp create }
             { temp create }
-            ptemp:=ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent,true);
+            usederef:=(p.resulttype.def.deftype in [arraydef,recorddef]) or
+                      is_shortstring(p.resulttype.def) or
+                      is_object(p.resulttype.def);
+            if usederef then
+              htype.setdef(tpointerdef.create(p.resulttype))
+            else
+              htype:=p.resulttype;
+            ptemp:=ctempcreatenode.create(htype,htype.def.size,tt_persistent,true);
+            if usederef then
+              begin
+                loadp:=caddrnode.create_internal(p);
+                refp:=cderefnode.create(ctemprefnode.create(ptemp));
+              end
+            else
+              begin
+                loadp:=p;
+                refp:=ctemprefnode.create(ptemp);
+              end;
             addstatement(newinitstatement,ptemp);
             addstatement(newinitstatement,ptemp);
             addstatement(newinitstatement,cassignmentnode.create(
             addstatement(newinitstatement,cassignmentnode.create(
                 ctemprefnode.create(ptemp),
                 ctemprefnode.create(ptemp),
-                p));
-            resulttypepass(aktcallnode.methodpointerinit);
+                loadp));
             { new tree is only a temp reference }
             { new tree is only a temp reference }
-            p:=ctemprefnode.create(ptemp);
-            resulttypepass(p);
+            p:=refp;
             { temp release }
             { temp release }
             addstatement(newdonestatement,ctempdeletenode.create(ptemp));
             addstatement(newdonestatement,ctempdeletenode.create(ptemp));
+            { call resulttypepass for new nodes }
+            resulttypepass(p);
+            resulttypepass(aktcallnode.methodpointerinit);
             resulttypepass(aktcallnode.methodpointerdone);
             resulttypepass(aktcallnode.methodpointerdone);
           end;
           end;
       end;
       end;
@@ -504,6 +529,8 @@ type
                  { set some settings needed for arrayconstructor }
                  { set some settings needed for arrayconstructor }
                  if is_array_constructor(left.resulttype.def) then
                  if is_array_constructor(left.resulttype.def) then
                   begin
                   begin
+                    if left.nodetype<>arrayconstructorn then
+                      internalerror(200504041);
                     if is_array_of_const(parasym.vartype.def) then
                     if is_array_of_const(parasym.vartype.def) then
                      begin
                      begin
                        { force variant array }
                        { force variant array }
@@ -2520,7 +2547,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.282  2005-03-28 15:05:17  peter
+  Revision 1.283  2005-04-05 21:07:43  peter
+    * load all complex loads of parameters that are needed multiple times
+      to a temp to prevent calling functions twice
+
+  Revision 1.282  2005/03/28 15:05:17  peter
   fix type of temps generated for parameters during inlining
   fix type of temps generated for parameters during inlining
 
 
   Revision 1.281  2005/03/25 22:20:18  peter
   Revision 1.281  2005/03/25 22:20:18  peter