Quellcode durchsuchen

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

Jonas Maebe vor 5 Jahren
Ursprung
Commit
1f5efe2a95
4 geänderte Dateien mit 64 neuen und 12 gelöschten Zeilen
  1. 10 1
      compiler/llvm/aasmllvmmetadata.pas
  2. 10 6
      compiler/llvm/llvminfo.pas
  3. 33 5
      compiler/llvm/nllvmcnv.pas
  4. 11 0
      rtl/inc/llvmintr.inc

+ 10 - 1
compiler/llvm/aasmllvmmetadata.pas

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

+ 10 - 6
compiler/llvm/llvminfo.pas

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

+ 33 - 5
compiler/llvm/nllvmcnv.pas

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

+ 11 - 0
rtl/inc/llvmintr.inc

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