+ inline trunc() support for the LLVM backend when using -Oofastmath (because

the behaviour of LLVM's fptosi instruction is undefined in case of
    overflow)

git-svn-id: trunk@36275 -
This commit is contained in:
Jonas Maebe 2017-05-20 19:28:15 +00:00
parent a5f22c92db
commit e4dbd24a49

View File

@ -32,27 +32,56 @@ interface
type
tllvminlinenode = class(tcginlinenode)
protected
procedure maybe_remove_round_trunc_typeconv;
function first_get_frame: tnode; override;
function first_abs_real: tnode; override;
function first_sqr_real: tnode; override;
function first_trunc_real: tnode; override;
public
procedure second_length; override;
procedure second_sqr_real; override;
procedure second_trunc_real; override;
end;
implementation
uses
verbose,globtype,constexp,
verbose,globals,globtype,constexp,
aasmbase, aasmdata,
symtype,symdef,defutil,
nutils,nadd,nbas,ncal,ncon,nflw,ninl,nld,nmat,
symconst,symtype,symdef,defutil,
nutils,nadd,nbas,ncal,ncnv,ncon,nflw,ninl,nld,nmat,
pass_2,
cgbase,cgutils,tgobj,hlcgobj,
cpubase,
llvmbase,aasmllvm;
procedure tllvminlinenode.maybe_remove_round_trunc_typeconv;
var
temp: tnode;
begin
{ the prototype of trunc()/round() in the system unit is declared
with valreal as parameter type, so the argument will always be
extended -> remove the typeconversion to extended if any; not done
in ninl, because there are other code generators that assume that
the parameter to trunc has been converted to valreal (e.g. PowerPC).
(copy from code in nx64inl, should be refactored)
}
if (left.nodetype=typeconvn) and
not(nf_explicit in left.flags) and
(ttypeconvnode(left).left.resultdef.typ=floatdef) then
begin
{ get rid of the type conversion, so the use_vectorfpu will be
applied to the original type }
temp:=ttypeconvnode(left).left;
ttypeconvnode(left).left:=nil;
left.free;
left:=temp;
end;
end;
function tllvminlinenode.first_get_frame: tnode;
begin
@ -127,6 +156,21 @@ implementation
end;
function tllvminlinenode.first_trunc_real: tnode;
begin
{ fptosi is undefined if the value is out of range -> only generate
in cast of fastmath }
if cs_opt_fastmath in current_settings.optimizerswitches then
begin
maybe_remove_round_trunc_typeconv;
expectloc:=LOC_REGISTER;
result:=nil;
end
else
result:=inherited;
end;
procedure tllvminlinenode.second_length;
var
lengthlab, nillab: tasmlabel;
@ -208,6 +252,21 @@ implementation
);
end;
procedure tllvminlinenode.second_trunc_real;
begin
secondpass(left);
if use_vectorfpu(left.resultdef) then
hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true)
else
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
current_asmdata.CurrAsmList.concat(
taillvm.op_reg_size_reg_size(la_fptosi,location.register,left.resultdef,left.location.register,resultdef)
);
end;
begin
cinlinenode:=tllvminlinenode;
end.