Browse Source

* simplify real expressions involving unary minus
+ test

florian 3 years ago
parent
commit
8cb92fd49a
2 changed files with 145 additions and 65 deletions
  1. 110 65
      compiler/nadd.pas
  2. 35 0
      tests/tbs/tb0685.pp

+ 110 - 65
compiler/nadd.pas

@@ -992,83 +992,128 @@ implementation
              exit;
              exit;
           end;
           end;
 
 
-        { optimize operations with real constants, but only if fast math is switched on as
-          the operations could change e.g. the sign of 0 so they cannot be optimized always
-        }
-        if (cs_opt_fastmath in current_settings.optimizerswitches) and
-          is_real(resultdef) then
+        if is_real(resultdef) then
           begin
           begin
-            if lt=realconstn then
+            if (nodetype=addn) then
               begin
               begin
-                if (trealconstnode(left).value_real=0) and (nodetype in [addn,muln,subn,slashn]) then
+                { -left+right => right-left,
+                  this operation is always valid }
+                if (left.nodetype=unaryminusn) then
                   begin
                   begin
-                    case nodetype of
-                      addn:
-                        begin
-                          result:=right.getcopy;
-                          exit;
-                        end;
-                      slashn,
-                      muln:
-                        if not(might_have_sideeffects(right,[mhs_exceptions])) then
-                          begin
-                            result:=left.getcopy;
-                            exit;
-                          end;
-                      subn:
-                        begin
-                          result:=ctypeconvnode.create_internal(cunaryminusnode.create(right.getcopy),right.resultdef);
-                          exit;
-                        end;
-                      else
-                        Internalerror(2020060801);
-                    end;
-                  end
-                else if (trealconstnode(left).value_real=1) and (nodetype=muln) then
+                    result:=caddnode.create(subn,right.getcopy,tunaryminusnode(left).left.getcopy);
+                    exit;
+                  end;
+
+                { left+(-right) => left-right,
+                  this operation is always valid }
+                if (right.nodetype=unaryminusn) then
                   begin
                   begin
-                    result:=right.getcopy;
+                    result:=caddnode.create(subn,left.getcopy,tunaryminusnode(right).left.getcopy);
                     exit;
                     exit;
                   end;
                   end;
-              end
-            else if rt=realconstn then
+              end;
+
+            { left-(-right) => left+right,
+              this operation is always valid }
+            if (nodetype=subn) and (right.nodetype=unaryminusn) then
+              begin
+                result:=caddnode.create(addn,left.getcopy,tunaryminusnode(right).left.getcopy);
+                exit;
+              end;
+
+            { (-left)*(-right) => left*right,
+              this operation is always valid }
+            if (nodetype=muln) and (left.nodetype=unaryminusn) and (right.nodetype=unaryminusn) then
+              begin
+                result:=caddnode.create(muln,tunaryminusnode(left).left.getcopy,tunaryminusnode(right).left.getcopy);
+                exit;
+              end;
+
+            { (-left)/(-right) => left/right,
+              this operation is always valid }
+            if (nodetype=slashn) and (left.nodetype=unaryminusn) and (right.nodetype=unaryminusn) then
               begin
               begin
-                if (trealconstnode(right).value_real=0) and (nodetype in [addn,muln,subn]) then
+                result:=caddnode.create(slashn,tunaryminusnode(left).left.getcopy,tunaryminusnode(right).left.getcopy);
+                exit;
+              end;
+
+            { optimize operations with real constants, but only if fast math is switched on as
+              the operations could change e.g. the sign of 0 so they cannot be optimized always
+            }
+            if is_real(resultdef) then
+              begin
+                if lt=realconstn then
                   begin
                   begin
-                    case nodetype of
-                      subn,
-                      addn:
-                        begin
-                          result:=left.getcopy;
-                          exit;
+                    if (trealconstnode(left).value_real=0) and (nodetype in [addn,muln,subn,slashn]) then
+                      begin
+                        case nodetype of
+                          addn:
+                            begin
+                              result:=right.getcopy;
+                              exit;
+                            end;
+                          slashn,
+                          muln:
+                            if not(might_have_sideeffects(right,[mhs_exceptions])) then
+                              begin
+                                result:=left.getcopy;
+                                exit;
+                              end;
+                          subn:
+                            begin
+                              result:=ctypeconvnode.create_internal(cunaryminusnode.create(right.getcopy),right.resultdef);
+                              exit;
+                            end;
+                          else
+                            Internalerror(2020060801);
                         end;
                         end;
-                      muln:
-                        if not(might_have_sideeffects(left,[mhs_exceptions])) then
-                          begin
-                            result:=right.getcopy;
-                            exit;
-                          end;
-                      else
-                        Internalerror(2020060802);
-                    end;
+                      end
+                    else if (trealconstnode(left).value_real=1) and (nodetype=muln) then
+                      begin
+                        result:=right.getcopy;
+                        exit;
+                      end;
                   end
                   end
-                else if (trealconstnode(right).value_real=1) and (nodetype in [muln,slashn]) then
+                else if rt=realconstn then
                   begin
                   begin
-                    result:=left.getcopy;
-                    exit;
+                    if (trealconstnode(right).value_real=0) and (nodetype in [addn,muln,subn]) then
+                      begin
+                        case nodetype of
+                          subn,
+                          addn:
+                            begin
+                              result:=left.getcopy;
+                              exit;
+                            end;
+                          muln:
+                            if not(might_have_sideeffects(left,[mhs_exceptions])) then
+                              begin
+                                result:=right.getcopy;
+                                exit;
+                              end;
+                          else
+                            Internalerror(2020060802);
+                        end;
+                      end
+                    else if (trealconstnode(right).value_real=1) and (nodetype in [muln,slashn]) then
+                      begin
+                        result:=left.getcopy;
+                        exit;
+                      end;
+                  end
+                { optimize a/a and a-a }
+                else if (cs_opt_level2 in current_settings.optimizerswitches) and  (nodetype in [slashn,subn]) and
+                  left.isequal(right) and not(might_have_sideeffects(left,[mhs_exceptions])) then
+                  begin
+                    case nodetype of
+                      subn:
+                        result:=crealconstnode.create(0,left.resultdef);
+                      slashn:
+                        result:=crealconstnode.create(1,left.resultdef);
+                      else
+                        Internalerror(2020060901);
+                    end;
                   end;
                   end;
-              end
-            { optimize a/a and a-a }
-            else if (cs_opt_level2 in current_settings.optimizerswitches) and  (nodetype in [slashn,subn]) and
-              left.isequal(right) and not(might_have_sideeffects(left,[mhs_exceptions])) then
-              begin
-                case nodetype of
-                  subn:
-                    result:=crealconstnode.create(0,left.resultdef);
-                  slashn:
-                    result:=crealconstnode.create(1,left.resultdef);
-                  else
-                    Internalerror(2020060901);
-                end;
               end;
               end;
           end;
           end;
 
 

+ 35 - 0
tests/tbs/tb0685.pp

@@ -0,0 +1,35 @@
+{ %OPT=-O- }
+
+var
+  d1,d2,d3 : double;
+
+begin
+  d1:=0.0;
+  d2:=-0.0;
+  d3:=-d1+d2;
+  writeln(d3);
+  if (d3<>0.0) or not(TDoubleRec(d3).Sign) then
+    halt(1);
+  d3:=d2+-d1;
+  writeln(d3);
+  if (d3<>0.0) or not(TDoubleRec(d3).Sign) then
+    halt(2);
+  d3:=d2--d1;
+  writeln(d3);
+  if (d3<>0.0) or (TDoubleRec(d3).Sign) then
+    halt(3);
+
+  d1:=1.0;
+  d2:=1.0;
+  d3:=-d2*-d1;
+  writeln(d3);
+  if (d3<>1.0) or (TDoubleRec(d3).Sign) then
+    halt(4);
+
+  d3:=-d2/-d1;
+  writeln(d3);
+  if (d3<>1.0) or (TDoubleRec(d3).Sign) then
+    halt(5);
+
+  writeln('ok');
+end.