LLVM: override thlcgobj.g_undefined_ok

Uses the freeze instruction available in LLVM 10.0+. If we don't freeze undef/
poison values before using them in a calculation (even if that calculation is
something like "and 0", which masks the result completely), the result will
still be undef/poison and will keep propagating.
This commit is contained in:
Jonas Maebe 2023-01-01 12:09:43 +01:00
parent ee0ad3ff86
commit ab581c5c30
5 changed files with 38 additions and 8 deletions

View File

@ -57,6 +57,8 @@ interface
{ e.g. dst = alloca size }
constructor op_ref_size(op:tllvmop;const dst:treference;size:tdef);
{ e.g. dst = freeze size src }
constructor op_reg_size_reg(op:tllvmop;dst:tregister;size:tdef;src:tregister);
{ e.g. dst = add size src1, src2 }
constructor op_reg_size_reg_reg(op:tllvmop;dst:tregister;size:tdef;src1,src2:tregister);
{ e.g. dst = shl size src1, 1 ( = src1 shl 1) }
@ -637,7 +639,8 @@ implementation
la_load,
la_icmp, la_fcmp,
la_phi, la_select,
la_va_arg, la_landingpad:
la_va_arg, la_landingpad,
la_freeze:
begin
if opnr=0 then
result:=operand_write
@ -855,6 +858,17 @@ implementation
end;
{ %dst = freeze i32 %src }
constructor taillvm.op_reg_size_reg(op: tllvmop; dst: tregister; size: tdef; src: tregister);
begin
create_llvm(op);
ops:=3;
loadreg(0,dst);
loaddef(1,size);
loadreg(2,src);
end;
{ %dst = add i32 %src1, %src2 }
constructor taillvm.op_reg_size_reg_reg(op: tllvmop; dst: tregister;size: tdef; src1, src2: tregister);
begin

View File

@ -98,6 +98,8 @@ uses
procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
procedure g_undefined_ok(list: TAsmList; size: tdef; reg: tregister); override;
procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
@ -1319,6 +1321,17 @@ implementation
end;
procedure thlcgllvm.g_undefined_ok(list: TAsmList; size: tdef; reg: tregister);
begin
if not(llvmflag_no_freeze in llvmversion_properties[current_settings.llvmversion]) then
begin
list.concat(taillvm.op_reg_size_reg(la_freeze,reg,size,reg));
exit;
end;
internalerror(2023010110);
end;
procedure thlcgllvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
var
tmpreg: tregister;

View File

@ -58,6 +58,7 @@ interface
'phi', 'select', 'call',
'va_arg', 'landingpad',
'blockaddress',
'freeze',
{ fpc pseudo opcodes }
'type', { type definition }
'catch', { catch exception }

View File

@ -66,6 +66,7 @@ interface
la_phi, la_select, la_call,
la_va_arg, la_landingpad,
la_blockaddress,
la_freeze,
{ fpc pseudo opcodes }
la_type, { type definition }
la_catch, { catch clause of a landingpad }

View File

@ -72,7 +72,8 @@ type
llvmflag_para_attr_type, { parameter attributes such as noalias and byval need to repeat the type }
llvmflag_opaque_ptr_transition, { initial opaque pointer introduction, needs to some elementtype attributes }
llvmflag_opaque_ptr, { only opaque pointers }
llvmflag_sanitizer_attributes { can use attributes to exclude symbols from sanitizers }
llvmflag_sanitizer_attributes, { can use attributes to exclude symbols from sanitizers }
llvmflag_no_freeze { lacks the freeze opcode to clear undefined/poison values }
);
tllvmversionflags = set of tllvmversionflag;
@ -124,12 +125,12 @@ Const
llvmversion_properties: array[tllvmversion] of tllvmversionflags =
(
{ invalid } [],
{ llvmver_7_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags],
{ llvmver_7_1 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags],
{ llvmver_8_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram],
{ llvmver_xc_11 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram],
{ llvmver_9_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext],
{ llvmver_xc_11_4 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext],
{ llvmver_7_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags,llvmflag_no_freeze],
{ llvmver_7_1 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags,llvmflag_no_freeze],
{ llvmver_8_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram,llvmflag_no_freeze],
{ llvmver_xc_11 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram,llvmflag_no_freeze],
{ llvmver_9_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_no_freeze],
{ llvmver_xc_11_4 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_no_freeze],
{ llvmver_10_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
{ llvmver_xc_12_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
{ llvmver_11_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid_new,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp,llvmflag_array_datalocation],