mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 02:48:07 +02:00
* support for constrained sitofp/uitofp with (the upcoming) LLVM 10.0
(fixes most of test/units/math/troundm, although there's still an LLVM optimizer/code generation bug that breaks some qword -> double conversions) git-svn-id: trunk@43829 -
This commit is contained in:
parent
9b53ed53e3
commit
1f5efe2a95
@ -129,11 +129,12 @@ interface
|
||||
|
||||
function llvm_getmetadatareftypedconst(metadata: tai_llvmbasemetadatanode): tai_simpletypedconst;
|
||||
|
||||
function llvm_constrainedexceptmodestring: ansistring;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose,
|
||||
verbose,globals,
|
||||
fmodule,
|
||||
symdef;
|
||||
|
||||
@ -142,6 +143,14 @@ implementation
|
||||
result:=tai_simpletypedconst.create(llvm_metadatatype, tai_llvmmetadatareftypedconst.create(metadata));
|
||||
end;
|
||||
|
||||
function llvm_constrainedexceptmodestring: ansistring;
|
||||
begin
|
||||
if not(cs_opt_fastmath in current_settings.optimizerswitches) then
|
||||
result:='fpexcept.strict'
|
||||
else
|
||||
result:='fpexcept.ignore'
|
||||
end;
|
||||
|
||||
procedure tai_llvmbasemetadatanode.addvalue(val: tai_abstracttypedconst);
|
||||
begin
|
||||
{ bypass string merging attempts, as we add tai_strings directly here }
|
||||
|
@ -41,14 +41,16 @@ Type
|
||||
llvmver_7_0,
|
||||
llvmver_7_1,
|
||||
llvmver_8_0,
|
||||
llvmver_9_0
|
||||
llvmver_9_0,
|
||||
llvmver_10_0
|
||||
);
|
||||
|
||||
type
|
||||
tllvmversionflag = (
|
||||
llvmflag_memcpy_indiv_align, { memcpy intrinsic supports separate alignment for source and dest }
|
||||
llvmflag_null_pointer_valid, { supports "llvmflag_null_pointer_valid" attribute, which indicates access to nil should not be optimized as undefined behaviour }
|
||||
llvmflag_constrained_fptrunc_fpext { supports constrained fptrunc and fpext intrinsics }
|
||||
llvmflag_memcpy_indiv_align, { memcpy intrinsic supports separate alignment for source and dest }
|
||||
llvmflag_null_pointer_valid, { supports "llvmflag_null_pointer_valid" attribute, which indicates access to nil should not be optimized as undefined behaviour }
|
||||
llvmflag_constrained_fptrunc_fpext, { supports constrained fptrunc and fpext intrinsics }
|
||||
llvmflag_constrained_fptoi_itofp { supports constrained fptosi/fptoui/uitofp/sitofp instrinsics }
|
||||
);
|
||||
tllvmversionflags = set of tllvmversionflag;
|
||||
|
||||
@ -60,7 +62,8 @@ Const
|
||||
'7.0',
|
||||
'7.1',
|
||||
'8.0',
|
||||
'9.0'
|
||||
'9.0',
|
||||
'10.0'
|
||||
);
|
||||
|
||||
llvmversion_properties: array[tllvmversion] of tllvmversionflags =
|
||||
@ -71,7 +74,8 @@ Const
|
||||
{ llvmver_7_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid],
|
||||
{ llvmver_7_1 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid],
|
||||
{ llvmver_8_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid],
|
||||
{ llvmver_9_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext]
|
||||
{ llvmver_9_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext],
|
||||
{ llvmver_10_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp]
|
||||
);
|
||||
|
||||
{ Supported optimizations, only used for information }
|
||||
|
@ -64,11 +64,11 @@ interface
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,globals,verbose,
|
||||
globtype,globals,cutils,verbose,
|
||||
aasmbase,aasmdata,
|
||||
llvmbase,aasmllvm,
|
||||
llvmbase,llvminfo,aasmllvm,aasmllvmmetadata,llvmdef,
|
||||
procinfo,
|
||||
ncal,
|
||||
ncal,ncon,
|
||||
symconst,symdef,defutil,
|
||||
cgbase,cgutils,tgobj,hlcgobj,pass_2;
|
||||
|
||||
@ -104,9 +104,37 @@ class function tllvmtypeconvnode.target_specific_need_equal_typeconv(fromdef, to
|
||||
|
||||
|
||||
function tllvmtypeconvnode.first_int_to_real: tnode;
|
||||
{$push}{$j+}
|
||||
const
|
||||
intrinfix: array[boolean] of string[7] =
|
||||
('uitofp','sitofp');
|
||||
{$pop}
|
||||
var
|
||||
exceptmode: ansistring;
|
||||
begin
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
result:=nil;
|
||||
if (llvmflag_constrained_fptoi_itofp in llvmversion_properties[current_settings.llvmversion]) and
|
||||
{ these are converted to 80 bits first in any case }
|
||||
not(tfloatdef(resultdef).floattype in [s64currency,s64comp]) and
|
||||
((left.resultdef.size>=resultdef.size) or
|
||||
((torddef(left.resultdef).ordtype=u64bit) and
|
||||
(tfloatdef(resultdef).floattype=s80real))) then
|
||||
begin
|
||||
{ in case rounding may have to be applied, use the intrinsic }
|
||||
exceptmode:=llvm_constrainedexceptmodestring;
|
||||
result:=ccallnode.createintern('llvm_experimental_constrained_'+intrinfix[is_signed(left.resultdef)]+llvmfloatintrinsicsuffix(tfloatdef(resultdef))+'_i'+tostr(left.resultdef.size*8),
|
||||
ccallparanode.create(cstringconstnode.createpchar(ansistring2pchar(exceptmode),length(exceptmode),llvm_metadatatype),
|
||||
ccallparanode.create(cstringconstnode.createpchar(ansistring2pchar('round.dynamic'),length('round.dynamic'),llvm_metadatatype),
|
||||
ccallparanode.create(left,nil)
|
||||
)
|
||||
)
|
||||
);
|
||||
left:=nil;
|
||||
end
|
||||
else
|
||||
begin
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -105,3 +105,14 @@ function llvm_experimental_constrained_fptrunc_f64_f128(a: float128; rounding, e
|
||||
function llvm_experimental_constrained_fpext_f128_f32(a: single; exceptions: LLVMMetadata): float128; compilerproc; external name 'llvm.experimental.constrained.fpext.f128.f32';
|
||||
function llvm_experimental_constrained_fpext_f128_f64(a: double; exceptions: LLVMMetadata): float128; compilerproc; external name 'llvm.experimental.constrained.fpext.f128.f64';
|
||||
{$endif}
|
||||
|
||||
{ only include the cases that may trigger rounding }
|
||||
function llvm_experimental_constrained_sitofp_f32_i32(val: longint; rounding, exceptions: LLVMMetadata): single; compilerproc; external name 'llvm.experimental.constrained.sitofp.f32.i32';
|
||||
function llvm_experimental_constrained_sitofp_f32_i64(val: int64; rounding, exceptions: LLVMMetadata): single; compilerproc; external name 'llvm.experimental.constrained.sitofp.f32.i64';
|
||||
function llvm_experimental_constrained_sitofp_f64_i64(val: int64; rounding, exceptions: LLVMMetadata): double; compilerproc; external name 'llvm.experimental.constrained.sitofp.f64.i64';
|
||||
function llvm_experimental_constrained_uitofp_f32_i32(val: cardinal; rounding, exceptions: LLVMMetadata): single; compilerproc; external name 'llvm.experimental.constrained.uitofp.f32.i32';
|
||||
function llvm_experimental_constrained_uitofp_f32_i64(val: qword; rounding, exceptions: LLVMMetadata): single; compilerproc; external name 'llvm.experimental.constrained.uitofp.f32.i64';
|
||||
function llvm_experimental_constrained_uitofp_f64_i64(val: qword; rounding, exceptions: LLVMMetadata): double; compilerproc; external name 'llvm.experimental.constrained.uitofp.f64.i64';
|
||||
{$ifdef SUPPORT_EXTENDED}
|
||||
function llvm_experimental_constrained_uitofp_f80_i64(val: qword; rounding, exceptions: LLVMMetadata): extended; compilerproc; external name 'llvm.experimental.constrained.uitofp.x86_fp80.i64';
|
||||
{$endif}
|
||||
|
Loading…
Reference in New Issue
Block a user