瀏覽代碼

* correctly take care of short boolean evaluation when rearranging nodes during CSE

git-svn-id: branches/laksen/riscv_new@39803 -
florian 6 年之前
父節點
當前提交
88f83280dc
共有 2 個文件被更改,包括 18 次插入7 次删除
  1. 12 1
      compiler/nutils.pas
  2. 6 6
      compiler/optcse.pas

+ 12 - 1
compiler/nutils.pas

@@ -161,6 +161,10 @@ interface
     { include or exclude cs from p.localswitches }
     { include or exclude cs from p.localswitches }
     procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean);
     procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean);
 
 
+    { returns true, if p is a node which shall be short boolean evaluated,
+      if it is not an orn/andn with boolean operans, the result is undefined }
+    function doshortbooleval(p : tnode) : Boolean;
+
 implementation
 implementation
 
 
     uses
     uses
@@ -1459,7 +1463,8 @@ implementation
           exclude(p.localswitches, plocalswitchchange(plsc)^.cs);
           exclude(p.localswitches, plocalswitchchange(plsc)^.cs);
         result:=fen_true;
         result:=fen_true;
      end;
      end;
-   
+
+
     procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean);
     procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean);
       var
       var
         lsc : tlocalswitchchange;
         lsc : tlocalswitchchange;
@@ -1469,4 +1474,10 @@ implementation
         foreachnodestatic(p,@do_change_local_settings,@lsc);
         foreachnodestatic(p,@do_change_local_settings,@lsc);
       end;
       end;
 
 
+
+    function doshortbooleval(p : tnode) : Boolean;
+      begin
+        Result:=(p.nodetype in [orn,andn]) and ((nf_short_bool in taddnode(p).flags) or not(cs_full_boolean_eval in p.localswitches));
+      end;
+
 end.
 end.

+ 6 - 6
compiler/optcse.pas

@@ -298,9 +298,9 @@ unit optcse;
             if not(csedomain) then
             if not(csedomain) then
               begin
               begin
                 { try to transform the tree to get better cse domains, consider:
                 { try to transform the tree to get better cse domains, consider:
-                       +
+                       +   (1)
                       / \
                       / \
-                     +   C
+                (2)  +   C
                     / \
                     / \
                    A   B
                    A   B
 
 
@@ -320,8 +320,7 @@ unit optcse;
                   { either if fastmath is on }
                   { either if fastmath is on }
                   ((cs_opt_fastmath in current_settings.optimizerswitches) or
                   ((cs_opt_fastmath in current_settings.optimizerswitches) or
                    { or for the logical operators, they cannot overflow }
                    { or for the logical operators, they cannot overflow }
-                   ((n.nodetype in [andn,orn]) and
-                    (n.localswitches*[cs_full_boolean_eval]=[])) or
+                   (n.nodetype in [andn,orn]) or
                    { or for integers if range checking is off }
                    { or for integers if range checking is off }
                    ((is_integer(n.resultdef) and
                    ((is_integer(n.resultdef) and
                     (n.localswitches*[cs_check_range,cs_check_overflow]=[]) and
                     (n.localswitches*[cs_check_range,cs_check_overflow]=[]) and
@@ -330,8 +329,9 @@ unit optcse;
                    (is_set(n.resultdef))
                    (is_set(n.resultdef))
                    ) then
                    ) then
                   while (n.nodetype=tbinarynode(n).left.nodetype) and
                   while (n.nodetype=tbinarynode(n).left.nodetype) and
-                        { don't swap elements with full boolean evaluation. this might not be safe }
-                        (tbinarynode(n).left.localswitches*[cs_full_boolean_eval]=[]) and
+                    { if node (1) is fully boolean evaluated and node (2) not, we cannot do the swap as is might result in B being evaluated always,
+                      the other way round is no problem, C is still evaluated only if needed }
+                    (not(is_boolean(n.resultdef)) or not(n.nodetype in [andn,orn]) or doshortbooleval(n) or not(doshortbooleval(tbinarynode(n).left))) and
                         { the resulttypes of the operands we'll swap must be equal,
                         { the resulttypes of the operands we'll swap must be equal,
                           required in case of a 32x32->64 multiplication, then we
                           required in case of a 32x32->64 multiplication, then we
                           cannot swap out one of the 32 bit operands for a 64 bit one
                           cannot swap out one of the 32 bit operands for a 64 bit one