mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-30 23:22:33 +02:00
+ very limited SSA support (only outside control flow
constructs for now) git-svn-id: trunk@3671 -
This commit is contained in:
parent
4bcfd1af9a
commit
e531c4f125
@ -148,6 +148,7 @@ implementation
|
||||
oldflowcontrol:=flowcontrol;
|
||||
oldclabel:=current_procinfo.CurrContinueLabel;
|
||||
oldblabel:=current_procinfo.CurrBreakLabel;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
|
||||
sync_regvars(true);
|
||||
{$ifdef OLDREGVARS}
|
||||
@ -199,7 +200,7 @@ implementation
|
||||
current_procinfo.CurrContinueLabel:=oldclabel;
|
||||
current_procinfo.CurrBreakLabel:=oldblabel;
|
||||
{ a break/continue in a while/repeat block can't be seen outside }
|
||||
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
|
||||
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
|
||||
end;
|
||||
|
||||
|
||||
@ -211,6 +212,7 @@ implementation
|
||||
|
||||
var
|
||||
hl,otlabel,oflabel : tasmlabel;
|
||||
oldflowcontrol: tflowcontrol;
|
||||
(*
|
||||
org_regvar_loaded_other,
|
||||
then_regvar_loaded_other,
|
||||
@ -226,6 +228,8 @@ implementation
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
oldflowcontrol := flowcontrol;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
otlabel:=current_procinfo.CurrTrueLabel;
|
||||
oflabel:=current_procinfo.CurrFalseLabel;
|
||||
current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
|
||||
@ -359,6 +363,7 @@ implementation
|
||||
|
||||
current_procinfo.CurrTrueLabel:=otlabel;
|
||||
current_procinfo.CurrFalseLabel:=oflabel;
|
||||
flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
|
||||
end;
|
||||
|
||||
|
||||
@ -416,6 +421,7 @@ implementation
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
oldflowcontrol:=flowcontrol;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
oldclabel:=current_procinfo.CurrContinueLabel;
|
||||
oldblabel:=current_procinfo.CurrBreakLabel;
|
||||
current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
|
||||
@ -759,7 +765,7 @@ implementation
|
||||
current_procinfo.CurrContinueLabel:=oldclabel;
|
||||
current_procinfo.CurrBreakLabel:=oldblabel;
|
||||
{ a break/continue in a while/repeat block can't be seen outside }
|
||||
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
|
||||
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
|
||||
end;
|
||||
|
||||
|
||||
@ -830,6 +836,7 @@ implementation
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
include(flowcontrol,fc_gotolabel);
|
||||
{$ifdef OLDREGVARS}
|
||||
load_all_regvars(current_asmdata.CurrAsmList);
|
||||
{$endif OLDREGVARS}
|
||||
@ -853,6 +860,7 @@ implementation
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
include(flowcontrol,fc_gotolabel);
|
||||
{$ifdef OLDREGVARS}
|
||||
load_all_regvars(current_asmdata.CurrAsmList);
|
||||
{$endif OLDREGVARS}
|
||||
|
@ -557,6 +557,8 @@ implementation
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ SSA support }
|
||||
maybechangeloadnodereg(left);
|
||||
case right.location.loc of
|
||||
LOC_CONSTANT :
|
||||
begin
|
||||
|
@ -683,6 +683,7 @@ implementation
|
||||
|
||||
procedure tcgcasenode.pass_2;
|
||||
var
|
||||
oldflowcontrol: tflowcontrol;
|
||||
i : longint;
|
||||
lv,hv,
|
||||
max_label: tconstexprint;
|
||||
@ -695,6 +696,8 @@ implementation
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
oldflowcontrol := flowcontrol;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
{ Allocate labels }
|
||||
current_asmdata.getjumplabel(endlabel);
|
||||
current_asmdata.getjumplabel(elselabel);
|
||||
@ -862,6 +865,7 @@ implementation
|
||||
{ Reset labels }
|
||||
for i:=0 to blocks.count-1 do
|
||||
pcaseblock(blocks[i])^.blocklabel:=nil;
|
||||
flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -101,6 +101,9 @@ interface
|
||||
// procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
|
||||
procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
|
||||
|
||||
{ if the result of n is a LOC_C(..)REGISTER, try to find the corresponding }
|
||||
{ loadn and change its location to a new register (= SSA) }
|
||||
procedure maybechangeloadnodereg(var n: tnode);
|
||||
|
||||
{#
|
||||
Allocate the buffers for exception management and setjmp environment.
|
||||
@ -167,6 +170,9 @@ implementation
|
||||
{$ifdef powerpc64}
|
||||
, cpupi
|
||||
{$endif}
|
||||
{$ifdef SUPPORT_MMX}
|
||||
, cgx86
|
||||
{$endif SUPPORT_MMX}
|
||||
;
|
||||
|
||||
|
||||
@ -2240,6 +2246,135 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
SSA support
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
preplaceregrec = ^treplaceregrec;
|
||||
treplaceregrec = record
|
||||
old, new: tregister;
|
||||
{$ifndef cpu64bit}
|
||||
oldhi, newhi: tregister;
|
||||
{$endif cpu64bit}
|
||||
ressym: tsym;
|
||||
end;
|
||||
|
||||
|
||||
function doreplace(var n: tnode; para: pointer): foreachnoderesult;
|
||||
var
|
||||
rr: preplaceregrec absolute para;
|
||||
begin
|
||||
result := fen_false;
|
||||
case n.nodetype of
|
||||
loadn:
|
||||
begin
|
||||
if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
|
||||
not assigned(tloadnode(n).left) and
|
||||
(((tloadnode(n).symtableentry <> rr^.ressym) and
|
||||
not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
|
||||
not(fc_exit in flowcontrol)) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
|
||||
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bit}
|
||||
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
|
||||
result := fen_norecurse_true;
|
||||
end;
|
||||
end;
|
||||
temprefn:
|
||||
begin
|
||||
if (ttemprefnode(n).tempinfo^.valid) and
|
||||
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
|
||||
(ttemprefnode(n).tempinfo^.location.register = rr^.old) then
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
{ it's possible a 64 bit location was shifted and/xor typecasted }
|
||||
{ in a 32 bit value, so only 1 register was left in the location }
|
||||
if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
|
||||
if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
|
||||
ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
|
||||
else
|
||||
exit;
|
||||
{$endif cpu64bit}
|
||||
ttemprefnode(n).tempinfo^.location.register := rr^.new;
|
||||
result := fen_norecurse_true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure maybechangeloadnodereg(var n: tnode);
|
||||
var
|
||||
rr: treplaceregrec;
|
||||
begin
|
||||
if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
|
||||
([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) then
|
||||
exit;
|
||||
rr.old := n.location.register;
|
||||
rr.ressym := nil;
|
||||
{$ifndef cpu64bit}
|
||||
rr.oldhi := NR_NO;
|
||||
{$endif cpu64bit}
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
rr.oldhi := n.location.register64.reghi;
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
|
||||
else
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
|
||||
assigned(current_procinfo.procdef.funcretsym) and
|
||||
(tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
|
||||
if (current_procinfo.procdef.proctypeoption=potype_constructor) then
|
||||
rr.ressym:=tsym(current_procinfo.procdef.parast.search('self'))
|
||||
else
|
||||
rr.ressym:=current_procinfo.procdef.funcretsym;
|
||||
|
||||
if not foreachnodestatic(n,@doreplace,@rr) then
|
||||
exit;
|
||||
|
||||
{ now that we've change the loadn/temp, also change the node result location }
|
||||
{$ifndef cpu64bit}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
begin
|
||||
n.location.register64.reglo := rr.new;
|
||||
n.location.register64.reghi := rr.newhi;
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
n.location.register := rr.new;
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_free_symtable(list:TAsmList;st:tsymtable);
|
||||
var
|
||||
sym : tsym;
|
||||
|
@ -29,7 +29,7 @@ uses
|
||||
node;
|
||||
|
||||
type
|
||||
tenumflowcontrol = (fc_exit,fc_break,fc_continue);
|
||||
tenumflowcontrol = (fc_exit,fc_break,fc_continue,fc_inflowcontrol,fc_gotolabel);
|
||||
tflowcontrol = set of tenumflowcontrol;
|
||||
|
||||
var
|
||||
|
Loading…
Reference in New Issue
Block a user