mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-13 13:29:24 +02:00
+ min/max support for x86
git-svn-id: trunk@47701 -
This commit is contained in:
parent
c0d75c1c69
commit
1a9678f4c4
@ -302,9 +302,9 @@ implementation
|
|||||||
{$ifdef i8086}
|
{$ifdef i8086}
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
{$endif i8086}
|
{$endif i8086}
|
||||||
{$ifdef xtensa}
|
{$if defined(xtensa) or defined(i386)}
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
{$endif xtensa}
|
{$endif defined(xtensa) or defined(i386)}
|
||||||
cgbase,procinfo
|
cgbase,procinfo
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1588,13 +1588,24 @@ implementation
|
|||||||
CGMessagePos(right.fileinfo,cg_w_unreachable_code);
|
CGMessagePos(right.fileinfo,cg_w_unreachable_code);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$if defined(xtensa)}
|
{$if defined(i386) or defined(x86_64) or defined(xtensa)}
|
||||||
{ use min/max intrinsic? }
|
{ use min/max intrinsic? }
|
||||||
if (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and IsSingleStatement(t1,elsestmnt) and
|
if (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and IsSingleStatement(t1,elsestmnt) and
|
||||||
(thenstmnt.nodetype=assignn) and (elsestmnt.nodetype=assignn) and
|
(thenstmnt.nodetype=assignn) and (elsestmnt.nodetype=assignn) and
|
||||||
not(might_have_sideeffects(left)) and
|
not(might_have_sideeffects(left)) and
|
||||||
tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left) and
|
tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left) and
|
||||||
|
{$if defined(i386) or defined(x86_64)}
|
||||||
|
{$ifdef i386}
|
||||||
|
(((current_settings.fputype>=fpu_sse) and is_single(tassignmentnode(thenstmnt).left.resultdef)) or
|
||||||
|
((current_settings.fputype>=fpu_sse2) and is_double(tassignmentnode(thenstmnt).left.resultdef))
|
||||||
|
) and
|
||||||
|
{$else i386}
|
||||||
|
(is_single(tassignmentnode(thenstmnt).left.resultdef) or is_double(tassignmentnode(thenstmnt).left.resultdef)) and
|
||||||
|
{$endif i386}
|
||||||
|
{$endif defined(i386) or defined(x86_64)}
|
||||||
|
{$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)}
|
||||||
((tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right))) or
|
((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).right) and (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left)))) then
|
||||||
begin
|
begin
|
||||||
@ -1627,7 +1638,7 @@ implementation
|
|||||||
ccallparanode.create(taddnode(left).left.getcopy,nil)))
|
ccallparanode.create(taddnode(left).left.getcopy,nil)))
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
{$endif defined(xtensa)}
|
{$endif defined(i386) or defined(x86_64) or defined(xtensa)}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ interface
|
|||||||
function first_fma: tnode; override;
|
function first_fma: tnode; override;
|
||||||
function first_frac_real : tnode; override;
|
function first_frac_real : tnode; override;
|
||||||
function first_int_real : tnode; override;
|
function first_int_real : tnode; override;
|
||||||
|
function first_minmax: tnode; override;
|
||||||
|
|
||||||
function simplify(forinline : boolean) : tnode; override;
|
function simplify(forinline : boolean) : tnode; override;
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ interface
|
|||||||
procedure second_frac_real;override;
|
procedure second_frac_real;override;
|
||||||
procedure second_int_real;override;
|
procedure second_int_real;override;
|
||||||
procedure second_high;override;
|
procedure second_high;override;
|
||||||
|
procedure second_minmax;override;
|
||||||
private
|
private
|
||||||
procedure load_fpu_location(lnode: tnode);
|
procedure load_fpu_location(lnode: tnode);
|
||||||
end;
|
end;
|
||||||
@ -389,6 +391,27 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tx86inlinenode.first_minmax: tnode;
|
||||||
|
begin
|
||||||
|
{$ifndef i8086}
|
||||||
|
if
|
||||||
|
{$ifdef i386}
|
||||||
|
((current_settings.fputype>=fpu_sse) and is_single(resultdef)) or
|
||||||
|
((current_settings.fputype>=fpu_sse2) and is_double(resultdef))
|
||||||
|
{$else i386}
|
||||||
|
((is_double(resultdef)) or (is_single(resultdef)))
|
||||||
|
{$endif i386}
|
||||||
|
then
|
||||||
|
begin
|
||||||
|
expectloc:=LOC_MMREGISTER;
|
||||||
|
Result:=nil;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{$endif i8086}
|
||||||
|
Result:=inherited first_minmax;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tx86inlinenode.simplify(forinline : boolean) : tnode;
|
function tx86inlinenode.simplify(forinline : boolean) : tnode;
|
||||||
var
|
var
|
||||||
temp : tnode;
|
temp : tnode;
|
||||||
@ -1401,4 +1424,117 @@ implementation
|
|||||||
location.register:=hregister;
|
location.register:=hregister;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tx86inlinenode.second_minmax;
|
||||||
|
const
|
||||||
|
oparray : array[false..true,false..true,s32real..s64real] of TAsmOp =
|
||||||
|
(
|
||||||
|
(
|
||||||
|
(A_MINSS,A_MINSD),
|
||||||
|
(A_VMINSS,A_VMINSD)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(A_MAXSS,A_MAXSD),
|
||||||
|
(A_VMAXSS,A_VMAXSD)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var
|
||||||
|
paraarray : array[1..2] of tnode;
|
||||||
|
memop,
|
||||||
|
i : integer;
|
||||||
|
gotmem : boolean;
|
||||||
|
op: TAsmOp;
|
||||||
|
begin
|
||||||
|
{$ifndef i8086}
|
||||||
|
if
|
||||||
|
{$ifdef i386}
|
||||||
|
((current_settings.fputype>=fpu_sse) and is_single(resultdef)) or
|
||||||
|
((current_settings.fputype>=fpu_sse2) and is_double(resultdef))
|
||||||
|
{$else i386}
|
||||||
|
is_single(resultdef) or is_double(resultdef)
|
||||||
|
{$endif i386}
|
||||||
|
then
|
||||||
|
begin
|
||||||
|
paraarray[1]:=tcallparanode(tcallparanode(parameters).nextpara).paravalue;
|
||||||
|
paraarray[2]:=tcallparanode(parameters).paravalue;
|
||||||
|
|
||||||
|
for i:=low(paraarray) to high(paraarray) do
|
||||||
|
secondpass(paraarray[i]);
|
||||||
|
|
||||||
|
{ only one memory operand is allowed }
|
||||||
|
gotmem:=false;
|
||||||
|
memop:=0;
|
||||||
|
for i:=low(paraarray) to high(paraarray) do
|
||||||
|
begin
|
||||||
|
if not(paraarray[i].location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
|
||||||
|
begin
|
||||||
|
if (paraarray[i].location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and not(gotmem) then
|
||||||
|
begin
|
||||||
|
memop:=i;
|
||||||
|
gotmem:=true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,paraarray[i].location,paraarray[i].resultdef,true);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
op:=oparray[inlinenumber in [in_max_single,in_max_double],UseAVX,tfloatdef(resultdef).floattype];
|
||||||
|
|
||||||
|
location_reset(location,LOC_MMREGISTER,paraarray[1].location.size);
|
||||||
|
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
|
||||||
|
|
||||||
|
if gotmem then
|
||||||
|
begin
|
||||||
|
if UseAVX then
|
||||||
|
case memop of
|
||||||
|
1:
|
||||||
|
emit_ref_reg_reg(op,S_NO,
|
||||||
|
paraarray[1].location.reference,paraarray[2].location.register,location.register);
|
||||||
|
2:
|
||||||
|
emit_ref_reg_reg(op,S_NO,
|
||||||
|
paraarray[2].location.reference,paraarray[1].location.register,location.register);
|
||||||
|
else
|
||||||
|
internalerror(2020120504);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
case memop of
|
||||||
|
1:
|
||||||
|
begin
|
||||||
|
hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,paraarray[2].resultdef,resultdef,
|
||||||
|
paraarray[2].location.register,location.register,mms_movescalar);
|
||||||
|
emit_ref_reg(op,S_NO,
|
||||||
|
paraarray[1].location.reference,location.register);
|
||||||
|
end;
|
||||||
|
2:
|
||||||
|
begin
|
||||||
|
hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,paraarray[1].resultdef,resultdef,
|
||||||
|
paraarray[1].location.register,location.register,mms_movescalar);
|
||||||
|
emit_ref_reg(op,S_NO,
|
||||||
|
paraarray[2].location.reference,location.register);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
internalerror(2020120601);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if UseAVX then
|
||||||
|
emit_reg_reg_reg(op,S_NO,
|
||||||
|
paraarray[1].location.register,paraarray[2].location.register,location.register)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,paraarray[1].resultdef,resultdef,
|
||||||
|
paraarray[1].location.register,location.register,mms_movescalar);
|
||||||
|
emit_reg_reg(op,S_NO,
|
||||||
|
paraarray[2].location.register,location.register)
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{$endif i8086}
|
||||||
|
internalerror(2020120503);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user