From 88a0d4d64bc49b3c18150773506a11a487467132 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 13 Dec 2020 09:52:44 +0000 Subject: [PATCH] + optimize if x>a then x:=a; into min(a,x);, similiar for max * test extended git-svn-id: trunk@47767 - --- compiler/nflw.pas | 25 ++-- tests/test/tminmax.pp | 318 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 320 insertions(+), 23 deletions(-) diff --git a/compiler/nflw.pas b/compiler/nflw.pas index 2cb6cbc377..6351c98c80 100644 --- a/compiler/nflw.pas +++ b/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} diff --git a/tests/test/tminmax.pp b/tests/test/tminmax.pp index 09f0db1e12..6dd398e2d7 100644 --- a/tests/test/tminmax.pp +++ b/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