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

* test extended

git-svn-id: trunk@47767 -
This commit is contained in:
florian 2020-12-13 09:52:44 +00:00
parent 53a4e6c513
commit 88a0d4d64b
2 changed files with 320 additions and 23 deletions

View File

@ -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}

View File

@ -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