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)}
         { use min/max intrinsic? }
         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
-          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)}
           { for now, limit it to fastmath mode as NaN handling is not implemented properly yet }
           (cs_opt_fastmath in current_settings.optimizerswitches) and
@@ -1610,8 +1610,9 @@ implementation
 {$if defined(xtensa)}
           (CPUXTENSA_HAS_MINMAX in cpu_capabilities[current_settings.cputype]) and is_32bitint(tassignmentnode(thenstmnt).right.resultdef) and
 {$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
             paratype:=tassignmentnode(thenstmnt).left.resultdef;
             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
               the second parameter is taken, we have to put the else part into the second parameter
               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;
 {$endif defined(i386) or defined(x86_64) or defined(xtensa)}
 {$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}
 uses
@@ -23,6 +23,7 @@ procedure TestSingle;
         Result := b;
     end;
 
+
   function Min2(a, b: Single): Single; inline;
     begin
       if a <= b then
@@ -40,6 +41,38 @@ procedure TestSingle;
         Result := b;
     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
     v1,v3,vNaN : Single;
 
@@ -54,6 +87,14 @@ procedure TestSingle;
       halt(3);
     if Max2(1,3)<>3 then
       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
       halt(11);
     if Max1(1,v3)<>3 then
@@ -62,6 +103,14 @@ procedure TestSingle;
       halt(13);
     if Max2(1,v3)<>3 then
       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
       halt(21);
     if Max1(1,v3)<>v3 then
@@ -70,6 +119,14 @@ procedure TestSingle;
       halt(23);
     if Max2(1,v3)<>v3 then
       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
       halt(31);
     if Max1(v1,v3)<>v3 then
@@ -78,6 +135,14 @@ procedure TestSingle;
       halt(33);
     if Max2(v1,v3)<>v3 then
       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]);
     vNaN:=NaN;
     if not(IsNaN(Min1(v1,vNaN))) then
@@ -96,6 +161,22 @@ procedure TestSingle;
       halt(47);
     if Max2(vNaN,v3)<>v3 then
       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([]);
   end;
 
@@ -118,6 +199,7 @@ procedure TestDouble;
         Result := b;
     end;
 
+
   function Min2(a, b: Double): Double; inline;
     begin
       if a <= b then
@@ -135,6 +217,38 @@ procedure TestDouble;
         Result := b;
     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
     v1,v3,vNaN : Double;
 
@@ -142,13 +256,21 @@ procedure TestDouble;
     v1:=1;
     v3:=3;
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(101);
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(102);
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(103);
     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
       halt(111);
     if Max1(1,v3)<>3 then
@@ -157,6 +279,14 @@ procedure TestDouble;
       halt(113);
     if Max2(1,v3)<>3 then
       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
       halt(121);
     if Max1(1,v3)<>v3 then
@@ -165,6 +295,14 @@ procedure TestDouble;
       halt(123);
     if Max2(1,v3)<>v3 then
       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
       halt(131);
     if Max1(v1,v3)<>v3 then
@@ -173,6 +311,14 @@ procedure TestDouble;
       halt(133);
     if Max2(v1,v3)<>v3 then
       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]);
     vNaN:=NaN;
     if not(IsNaN(Min1(v1,vNaN))) then
@@ -191,6 +337,22 @@ procedure TestDouble;
       halt(147);
     if Max2(vNaN,v3)<>v3 then
       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([]);
   end;
 
@@ -214,6 +376,7 @@ procedure TestDWord;
         Result := b;
     end;
 
+
   function Min2(a, b: DWord): DWord; inline;
     begin
       if a <= b then
@@ -231,6 +394,38 @@ procedure TestDWord;
         Result := b;
     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
     v1,v3 : DWord;
 
@@ -238,13 +433,21 @@ procedure TestDWord;
     v1:=1;
     v3:=3;
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(201);
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(202);
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(203);
     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
       halt(211);
     if Max1(1,v3)<>3 then
@@ -253,6 +456,14 @@ procedure TestDWord;
       halt(213);
     if Max2(1,v3)<>3 then
       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
       halt(221);
     if Max1(1,v3)<>v3 then
@@ -261,6 +472,14 @@ procedure TestDWord;
       halt(223);
     if Max2(1,v3)<>v3 then
       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
       halt(231);
     if Max1(v1,v3)<>v3 then
@@ -269,6 +488,14 @@ procedure TestDWord;
       halt(233);
     if Max2(v1,v3)<>v3 then
       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;
 
 procedure TestLongint;
@@ -307,6 +534,38 @@ procedure TestLongint;
         Result := b;
     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
     v1,v3 : Longint;
 
@@ -314,13 +573,21 @@ procedure TestLongint;
     v1:=1;
     v3:=3;
     if Min1(1,3)<>1 then
-      halt(1);
+      halt(301);
     if Max1(1,3)<>3 then
-      halt(2);
+      halt(302);
     if Min2(1,3)<>1 then
-      halt(3);
+      halt(303);
     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
       halt(311);
     if Max1(1,v3)<>3 then
@@ -329,6 +596,14 @@ procedure TestLongint;
       halt(313);
     if Max2(1,v3)<>3 then
       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
       halt(321);
     if Max1(1,v3)<>v3 then
@@ -337,7 +612,14 @@ procedure TestLongint;
       halt(323);
     if Max2(1,v3)<>v3 then
       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
       halt(331);
     if Max1(v1,v3)<>v3 then
@@ -346,6 +628,14 @@ procedure TestLongint;
       halt(333);
     if Max2(v1,v3)<>v3 then
       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;
 
 begin