Browse Source

+ optimize if x>a then x:=a; into min(a,x);, similiar for max
* test extended

git-svn-id: trunk@47767 -

florian 4 years ago
parent
commit
88a0d4d64b
2 changed files with 320 additions and 23 deletions
  1. 16 9
      compiler/nflw.pas
  2. 304 14
      tests/test/tminmax.pp

+ 16 - 9
compiler/nflw.pas

@@ -1592,10 +1592,10 @@ implementation
 {$if defined(i386) or defined(x86_64) or defined(xtensa)}
 {$if defined(i386) or defined(x86_64) or defined(xtensa)}
         { use min/max intrinsic? }
         { use min/max intrinsic? }
         if (cs_opt_level2 in current_settings.optimizerswitches) and
         if (cs_opt_level2 in current_settings.optimizerswitches) and
-           (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and IsSingleStatement(t1,elsestmnt) and
-          (thenstmnt.nodetype=assignn) and (elsestmnt.nodetype=assignn) and
+           (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and ((t1=nil) or IsSingleStatement(t1,elsestmnt)) and
+          (thenstmnt.nodetype=assignn) and ((t1=nil) or (elsestmnt.nodetype=assignn)) and
           not(might_have_sideeffects(left)) and
           not(might_have_sideeffects(left)) and
-          tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left) and
+          ((t1=nil) or tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left)) and
 {$if defined(i386) or defined(x86_64)}
 {$if defined(i386) or defined(x86_64)}
           { for now, limit it to fastmath mode as NaN handling is not implemented properly yet }
           { for now, limit it to fastmath mode as NaN handling is not implemented properly yet }
           (cs_opt_fastmath in current_settings.optimizerswitches) and
           (cs_opt_fastmath in current_settings.optimizerswitches) and
@@ -1610,8 +1610,9 @@ implementation
 {$if defined(xtensa)}
 {$if defined(xtensa)}
           (CPUXTENSA_HAS_MINMAX in cpu_capabilities[current_settings.cputype]) and is_32bitint(tassignmentnode(thenstmnt).right.resultdef) and
           (CPUXTENSA_HAS_MINMAX in cpu_capabilities[current_settings.cputype]) and is_32bitint(tassignmentnode(thenstmnt).right.resultdef) and
 {$endif defined(xtensa)}
 {$endif defined(xtensa)}
-          ((tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right))) or
-           (tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left)))) then
+          ((tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and ((t1=nil) or (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right)))) or
+           (tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and ((t1=nil) or (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left))))
+          ) then
           begin
           begin
             paratype:=tassignmentnode(thenstmnt).left.resultdef;
             paratype:=tassignmentnode(thenstmnt).left.resultdef;
             if ((left.nodetype in [gtn,gten]) and
             if ((left.nodetype in [gtn,gten]) and
@@ -1644,10 +1645,16 @@ implementation
               Due to the defined behaviour for the min/max intrinsics that in case of a NaN
               Due to the defined behaviour for the min/max intrinsics that in case of a NaN
               the second parameter is taken, we have to put the else part into the second parameter
               the second parameter is taken, we have to put the else part into the second parameter
               thus pass it to the first callparanode call }
               thus pass it to the first callparanode call }
-            Result:=cassignmentnode.create_internal(tassignmentnode(thenstmnt).left.getcopy,
-              cinlinenode.create(in_nr,false,ccallparanode.create(tassignmentnode(elsestmnt).right.getcopy,
-                    ccallparanode.create(tassignmentnode(thenstmnt).right.getcopy,nil)))
-              );
+            if t1=nil then
+              Result:=cassignmentnode.create_internal(tassignmentnode(thenstmnt).left.getcopy,
+                cinlinenode.create(in_nr,false,ccallparanode.create(tassignmentnode(thenstmnt).left.getcopy,
+                      ccallparanode.create(tassignmentnode(thenstmnt).right.getcopy,nil)))
+                )
+            else
+              Result:=cassignmentnode.create_internal(tassignmentnode(thenstmnt).left.getcopy,
+                cinlinenode.create(in_nr,false,ccallparanode.create(tassignmentnode(elsestmnt).right.getcopy,
+                      ccallparanode.create(tassignmentnode(thenstmnt).right.getcopy,nil)))
+                );
           end;
           end;
 {$endif defined(i386) or defined(x86_64) or defined(xtensa)}
 {$endif defined(i386) or defined(x86_64) or defined(xtensa)}
 {$endif llvm}
 {$endif llvm}

+ 304 - 14
tests/test/tminmax.pp

@@ -1,4 +1,4 @@
-{ %opt=-O- -Oonofastmath }  { with fast math, the operands of min/max might be swapped and this breaks the tests using NaN }
+{ %opt=-Oonofastmath }  { with fast math, the operands of min/max might be swapped and this breaks the tests using NaN }
 
 
 {$mode objfpc}
 {$mode objfpc}
 uses
 uses
@@ -23,6 +23,7 @@ procedure TestSingle;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
   function Min2(a, b: Single): Single; inline;
   function Min2(a, b: Single): Single; inline;
     begin
     begin
       if a <= b then
       if a <= b then
@@ -40,6 +41,38 @@ procedure TestSingle;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
+  function Min3(a, b: Single): Single; inline;
+    begin
+      Result := b;
+      if a < b then
+        Result := a;
+    end;
+
+
+  function Max3(a, b: Single): Single; inline;
+    begin
+      Result := b;
+      if a > b then
+        Result := a;
+    end;
+
+
+  function Min4(a, b: Single): Single; inline;
+    begin
+      Result := b;
+      if a <= b then
+        Result := a;
+    end;
+
+
+  function Max4(a, b: Single): Single; inline;
+    begin
+      Result := b;
+      if a >= b then
+        Result := a;
+    end;
+
   var
   var
     v1,v3,vNaN : Single;
     v1,v3,vNaN : Single;
 
 
@@ -54,6 +87,14 @@ procedure TestSingle;
       halt(3);
       halt(3);
     if Max2(1,3)<>3 then
     if Max2(1,3)<>3 then
       halt(4);
       halt(4);
+    if Min3(1,3)<>1 then
+      halt(5);
+    if Max3(1,3)<>3 then
+      halt(6);
+    if Min3(1,3)<>1 then
+      halt(7);
+    if Max3(1,3)<>3 then
+      halt(8);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(11);
       halt(11);
     if Max1(1,v3)<>3 then
     if Max1(1,v3)<>3 then
@@ -62,6 +103,14 @@ procedure TestSingle;
       halt(13);
       halt(13);
     if Max2(1,v3)<>3 then
     if Max2(1,v3)<>3 then
       halt(14);
       halt(14);
+    if Min3(1,v3)<>1 then
+      halt(15);
+    if Max3(1,v3)<>3 then
+      halt(16);
+    if Min4(1,v3)<>1 then
+      halt(17);
+    if Max4(1,v3)<>3 then
+      halt(18);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(21);
       halt(21);
     if Max1(1,v3)<>v3 then
     if Max1(1,v3)<>v3 then
@@ -70,6 +119,14 @@ procedure TestSingle;
       halt(23);
       halt(23);
     if Max2(1,v3)<>v3 then
     if Max2(1,v3)<>v3 then
       halt(24);
       halt(24);
+    if Min3(1,v3)<>1 then
+      halt(25);
+    if Max3(1,v3)<>v3 then
+      halt(26);
+    if Min4(1,v3)<>1 then
+      halt(27);
+    if Max4(1,v3)<>v3 then
+      halt(28);
     if Min1(v1,v3)<>v1 then
     if Min1(v1,v3)<>v1 then
       halt(31);
       halt(31);
     if Max1(v1,v3)<>v3 then
     if Max1(v1,v3)<>v3 then
@@ -78,6 +135,14 @@ procedure TestSingle;
       halt(33);
       halt(33);
     if Max2(v1,v3)<>v3 then
     if Max2(v1,v3)<>v3 then
       halt(34);
       halt(34);
+    if Min3(v1,v3)<>v1 then
+      halt(35);
+    if Max3(v1,v3)<>v3 then
+      halt(36);
+    if Min4(v1,v3)<>v1 then
+      halt(37);
+    if Max4(v1,v3)<>v3 then
+      halt(38);
     SetExceptionMask([exInvalidOp]);
     SetExceptionMask([exInvalidOp]);
     vNaN:=NaN;
     vNaN:=NaN;
     if not(IsNaN(Min1(v1,vNaN))) then
     if not(IsNaN(Min1(v1,vNaN))) then
@@ -96,6 +161,22 @@ procedure TestSingle;
       halt(47);
       halt(47);
     if Max2(vNaN,v3)<>v3 then
     if Max2(vNaN,v3)<>v3 then
       halt(48);
       halt(48);
+    if not(IsNaN(Min3(v1,vNaN))) then
+      halt(49);
+    if Min3(NaN,v1)<>v1 then
+      halt(50);
+    if not(IsNaN(Max3(v1,vNaN))) then
+      halt(51);
+    if Max3(vNaN,v3)<>v3 then
+      halt(52);
+    if not(IsNaN(Min4(v1,vNaN))) then
+      halt(53);
+    if Min4(vNaN,v3)<>v3 then
+      halt(54);
+    if not(IsNaN(Max4(v1,vNaN))) then
+      halt(55);
+    if Max4(vNaN,v3)<>v3 then
+      halt(56);
     SetExceptionMask([]);
     SetExceptionMask([]);
   end;
   end;
 
 
@@ -118,6 +199,7 @@ procedure TestDouble;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
   function Min2(a, b: Double): Double; inline;
   function Min2(a, b: Double): Double; inline;
     begin
     begin
       if a <= b then
       if a <= b then
@@ -135,6 +217,38 @@ procedure TestDouble;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
+  function Min3(a, b: Double): Double; inline;
+    begin
+      Result := b;
+      if a < b then
+        Result := a;
+    end;
+
+
+  function Max3(a, b: Double): Double; inline;
+    begin
+      Result := b;
+      if a > b then
+        Result := a;
+    end;
+
+
+  function Min4(a, b: Double): Double; inline;
+    begin
+      Result := b;
+      if a <= b then
+        Result := a;
+    end;
+
+
+  function Max4(a, b: Double): Double; inline;
+    begin
+      Result := b;
+      if a >= b then
+        Result := a;
+    end;
+
   var
   var
     v1,v3,vNaN : Double;
     v1,v3,vNaN : Double;
 
 
@@ -142,13 +256,21 @@ procedure TestDouble;
     v1:=1;
     v1:=1;
     v3:=3;
     v3:=3;
     if Min1(1,3)<>1 then
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(101);
     if Max1(1,3)<>3 then
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(102);
     if Min2(1,3)<>1 then
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(103);
     if Max2(1,3)<>3 then
     if Max2(1,3)<>3 then
-      halt(4);
+      halt(104);
+    if Min3(1,3)<>1 then
+      halt(105);
+    if Max3(1,3)<>3 then
+      halt(106);
+    if Min3(1,3)<>1 then
+      halt(107);
+    if Max3(1,3)<>3 then
+      halt(108);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(111);
       halt(111);
     if Max1(1,v3)<>3 then
     if Max1(1,v3)<>3 then
@@ -157,6 +279,14 @@ procedure TestDouble;
       halt(113);
       halt(113);
     if Max2(1,v3)<>3 then
     if Max2(1,v3)<>3 then
       halt(114);
       halt(114);
+    if Min3(1,v3)<>1 then
+      halt(115);
+    if Max3(1,v3)<>3 then
+      halt(116);
+    if Min4(1,v3)<>1 then
+      halt(117);
+    if Max4(1,v3)<>3 then
+      halt(118);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(121);
       halt(121);
     if Max1(1,v3)<>v3 then
     if Max1(1,v3)<>v3 then
@@ -165,6 +295,14 @@ procedure TestDouble;
       halt(123);
       halt(123);
     if Max2(1,v3)<>v3 then
     if Max2(1,v3)<>v3 then
       halt(124);
       halt(124);
+    if Min3(1,v3)<>1 then
+      halt(125);
+    if Max3(1,v3)<>v3 then
+      halt(126);
+    if Min4(1,v3)<>1 then
+      halt(127);
+    if Max4(1,v3)<>v3 then
+      halt(128);
     if Min1(v1,v3)<>v1 then
     if Min1(v1,v3)<>v1 then
       halt(131);
       halt(131);
     if Max1(v1,v3)<>v3 then
     if Max1(v1,v3)<>v3 then
@@ -173,6 +311,14 @@ procedure TestDouble;
       halt(133);
       halt(133);
     if Max2(v1,v3)<>v3 then
     if Max2(v1,v3)<>v3 then
       halt(134);
       halt(134);
+    if Min3(v1,v3)<>v1 then
+      halt(135);
+    if Max3(v1,v3)<>v3 then
+      halt(136);
+    if Min4(v1,v3)<>v1 then
+      halt(137);
+    if Max4(v1,v3)<>v3 then
+      halt(138);
     SetExceptionMask([exInvalidOp]);
     SetExceptionMask([exInvalidOp]);
     vNaN:=NaN;
     vNaN:=NaN;
     if not(IsNaN(Min1(v1,vNaN))) then
     if not(IsNaN(Min1(v1,vNaN))) then
@@ -191,6 +337,22 @@ procedure TestDouble;
       halt(147);
       halt(147);
     if Max2(vNaN,v3)<>v3 then
     if Max2(vNaN,v3)<>v3 then
       halt(148);
       halt(148);
+    if not(IsNaN(Min3(v1,vNaN))) then
+      halt(149);
+    if Min3(NaN,v1)<>v1 then
+      halt(150);
+    if not(IsNaN(Max3(v1,vNaN))) then
+      halt(151);
+    if Max3(vNaN,v3)<>v3 then
+      halt(152);
+    if not(IsNaN(Min4(v1,vNaN))) then
+      halt(153);
+    if Min4(vNaN,v3)<>v3 then
+      halt(154);
+    if not(IsNaN(Max4(v1,vNaN))) then
+      halt(155);
+    if Max4(vNaN,v3)<>v3 then
+      halt(156);
     SetExceptionMask([]);
     SetExceptionMask([]);
   end;
   end;
 
 
@@ -214,6 +376,7 @@ procedure TestDWord;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
   function Min2(a, b: DWord): DWord; inline;
   function Min2(a, b: DWord): DWord; inline;
     begin
     begin
       if a <= b then
       if a <= b then
@@ -231,6 +394,38 @@ procedure TestDWord;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
+  function Min3(a, b: DWord): DWord; inline;
+    begin
+      Result := b;
+      if a < b then
+        Result := a;
+    end;
+
+
+  function Max3(a, b: DWord): DWord; inline;
+    begin
+      Result := b;
+      if a > b then
+        Result := a;
+    end;
+
+
+  function Min4(a, b: DWord): DWord; inline;
+    begin
+      Result := b;
+      if a <= b then
+        Result := a;
+    end;
+
+
+  function Max4(a, b: Double): Double; inline;
+    begin
+      Result := b;
+      if a >= b then
+        Result := a;
+    end;
+
   var
   var
     v1,v3 : DWord;
     v1,v3 : DWord;
 
 
@@ -238,13 +433,21 @@ procedure TestDWord;
     v1:=1;
     v1:=1;
     v3:=3;
     v3:=3;
     if Min1(1,3)<>1 then
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(201);
     if Max1(1,3)<>3 then
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(202);
     if Min2(1,3)<>1 then
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(203);
     if Max2(1,3)<>3 then
     if Max2(1,3)<>3 then
-      halt(4);
+      halt(204);
+    if Min3(1,3)<>1 then
+      halt(205);
+    if Max3(1,3)<>3 then
+      halt(206);
+    if Min3(1,3)<>1 then
+      halt(207);
+    if Max3(1,3)<>3 then
+      halt(208);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(211);
       halt(211);
     if Max1(1,v3)<>3 then
     if Max1(1,v3)<>3 then
@@ -253,6 +456,14 @@ procedure TestDWord;
       halt(213);
       halt(213);
     if Max2(1,v3)<>3 then
     if Max2(1,v3)<>3 then
       halt(214);
       halt(214);
+    if Min3(1,v3)<>1 then
+      halt(215);
+    if Max3(1,v3)<>3 then
+      halt(216);
+    if Min4(1,v3)<>1 then
+      halt(217);
+    if Max4(1,v3)<>3 then
+      halt(218);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(221);
       halt(221);
     if Max1(1,v3)<>v3 then
     if Max1(1,v3)<>v3 then
@@ -261,6 +472,14 @@ procedure TestDWord;
       halt(223);
       halt(223);
     if Max2(1,v3)<>v3 then
     if Max2(1,v3)<>v3 then
       halt(224);
       halt(224);
+    if Min3(1,v3)<>1 then
+      halt(225);
+    if Max3(1,v3)<>v3 then
+      halt(226);
+    if Min4(1,v3)<>1 then
+      halt(227);
+    if Max4(1,v3)<>v3 then
+      halt(228);
     if Min1(v1,v3)<>v1 then
     if Min1(v1,v3)<>v1 then
       halt(231);
       halt(231);
     if Max1(v1,v3)<>v3 then
     if Max1(v1,v3)<>v3 then
@@ -269,6 +488,14 @@ procedure TestDWord;
       halt(233);
       halt(233);
     if Max2(v1,v3)<>v3 then
     if Max2(v1,v3)<>v3 then
       halt(234);
       halt(234);
+    if Min3(v1,v3)<>v1 then
+      halt(235);
+    if Max3(v1,v3)<>v3 then
+      halt(236);
+    if Min4(v1,v3)<>v1 then
+      halt(237);
+    if Max4(v1,v3)<>v3 then
+      halt(238);
   end;
   end;
 
 
 procedure TestLongint;
 procedure TestLongint;
@@ -307,6 +534,38 @@ procedure TestLongint;
         Result := b;
         Result := b;
     end;
     end;
 
 
+
+  function Min3(a, b: Longint): Longint; inline;
+    begin
+      Result := b;
+      if a < b then
+        Result := a;
+    end;
+
+
+  function Max3(a, b: Longint): Longint; inline;
+    begin
+      Result := b;
+      if a > b then
+        Result := a;
+    end;
+
+
+  function Min4(a, b: Longint): Longint; inline;
+    begin
+      Result := b;
+      if a <= b then
+        Result := a;
+    end;
+
+
+  function Max4(a, b: Longint): Longint; inline;
+    begin
+      Result := b;
+      if a >= b then
+        Result := a;
+    end;
+
   var
   var
     v1,v3 : Longint;
     v1,v3 : Longint;
 
 
@@ -314,13 +573,21 @@ procedure TestLongint;
     v1:=1;
     v1:=1;
     v3:=3;
     v3:=3;
     if Min1(1,3)<>1 then
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(301);
     if Max1(1,3)<>3 then
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(302);
     if Min2(1,3)<>1 then
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(303);
     if Max2(1,3)<>3 then
     if Max2(1,3)<>3 then
-      halt(4);
+      halt(304);
+    if Min3(1,3)<>1 then
+      halt(305);
+    if Max3(1,3)<>3 then
+      halt(306);
+    if Min3(1,3)<>1 then
+      halt(307);
+    if Max3(1,3)<>3 then
+      halt(308);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(311);
       halt(311);
     if Max1(1,v3)<>3 then
     if Max1(1,v3)<>3 then
@@ -329,6 +596,14 @@ procedure TestLongint;
       halt(313);
       halt(313);
     if Max2(1,v3)<>3 then
     if Max2(1,v3)<>3 then
       halt(314);
       halt(314);
+    if Min3(1,v3)<>1 then
+      halt(315);
+    if Max3(1,v3)<>3 then
+      halt(316);
+    if Min4(1,v3)<>1 then
+      halt(317);
+    if Max4(1,v3)<>3 then
+      halt(318);
     if Min1(1,v3)<>1 then
     if Min1(1,v3)<>1 then
       halt(321);
       halt(321);
     if Max1(1,v3)<>v3 then
     if Max1(1,v3)<>v3 then
@@ -337,7 +612,14 @@ procedure TestLongint;
       halt(323);
       halt(323);
     if Max2(1,v3)<>v3 then
     if Max2(1,v3)<>v3 then
       halt(324);
       halt(324);
-    v1:=1;
+    if Min3(1,v3)<>1 then
+      halt(325);
+    if Max3(1,v3)<>v3 then
+      halt(326);
+    if Min4(1,v3)<>1 then
+      halt(327);
+    if Max4(1,v3)<>v3 then
+      halt(328);
     if Min1(v1,v3)<>v1 then
     if Min1(v1,v3)<>v1 then
       halt(331);
       halt(331);
     if Max1(v1,v3)<>v3 then
     if Max1(v1,v3)<>v3 then
@@ -346,6 +628,14 @@ procedure TestLongint;
       halt(333);
       halt(333);
     if Max2(v1,v3)<>v3 then
     if Max2(v1,v3)<>v3 then
       halt(334);
       halt(334);
+    if Min3(v1,v3)<>v1 then
+      halt(335);
+    if Max3(v1,v3)<>v3 then
+      halt(336);
+    if Min4(v1,v3)<>v1 then
+      halt(337);
+    if Max4(v1,v3)<>v3 then
+      halt(338);
   end;
   end;
 
 
 begin
 begin