* 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:
Jonas Maebe 2019-12-31 18:05:54 +00:00
parent 9b53ed53e3
commit 1f5efe2a95
4 changed files with 64 additions and 12 deletions

View File

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

View File

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

View File

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

View File

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