diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas index 947210311d..5d3b9cc76d 100644 --- a/compiler/i386/csopt386.pas +++ b/compiler/i386/csopt386.pas @@ -140,7 +140,7 @@ begin end end; else - for opCount := 1 to MaxCh do + for opCount := 1 to maxinschanges do case InsProp[p.opcode].Ch[opCount] of Ch_MOp1,CH_WOp1,CH_RWOp1: if not(onlymem) or @@ -904,7 +904,7 @@ begin begin NoHardCodedRegs := true; with InsProp[p.opcode] do - for chCount := 1 to MaxCh do + for chCount := 1 to maxinschanges do if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then begin NoHardCodedRegs := false; @@ -1058,7 +1058,7 @@ begin { updateStates(orgReg,newReg,p,false);} doReplaceReadReg := true; end; - for opCount := 1 to MaxCh do + for opCount := 1 to maxinschanges do case InsProp[p.opcode].Ch[opCount] of Ch_ROp1: if p.oper[0]^.typ = top_reg then @@ -1901,7 +1901,7 @@ begin ptaiprop(tai(p).optinfo)^.CanBeRemoved := True; else begin - for cnt := 1 to maxch do + for cnt := 1 to maxinschanges do begin case InsProp[taicpu(p).opcode].Ch[cnt] of Ch_ROp1: @@ -2109,7 +2109,14 @@ end. { $Log$ - Revision 1.65 2004-09-21 17:25:12 peter + Revision 1.66 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.65 2004/09/21 17:25:12 peter * paraloc branch merged Revision 1.64.4.1 2004/09/20 19:28:23 peter diff --git a/compiler/i386/daopt386.pas b/compiler/i386/daopt386.pas index 20549c78d3..029e4cd40f 100644 --- a/compiler/i386/daopt386.pas +++ b/compiler/i386/daopt386.pas @@ -725,7 +725,7 @@ begin RegReadByInstruction := true; exit end; - for opcount := 1 to maxch do + for opcount := 1 to maxinschanges do case insprop[p.opcode].ch[opcount] of CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI: if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then @@ -791,7 +791,7 @@ begin (supreg in [RS_EAX,RS_EDX]) else begin - for opcount := 1 to MaxCh do + for opcount := 1 to maxinschanges do case insprop[p.opcode].Ch[opCount] of CH_REAX..CH_MEDI: if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then @@ -866,7 +866,7 @@ begin begin Cnt := 1; InstrProp := InsProp[taicpu(p1).OpCode]; - while (Cnt <= MaxCh) and + while (Cnt <= maxinschanges) and (InstrProp.Ch[Cnt] <> Ch_None) and not(TmpResult) Do begin @@ -901,7 +901,7 @@ begin case p.typ of ait_instruction: begin - for l := 1 to MaxCh do + for l := 1 to maxinschanges do if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then exit; end; @@ -920,7 +920,7 @@ begin case p.typ of ait_instruction: begin - for l := 1 to MaxCh do + for l := 1 to maxinschanges do if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then exit; end; @@ -2555,7 +2555,7 @@ begin else begin Cnt := 1; - while (Cnt <= MaxCh) and + while (Cnt <= maxinschanges) and (InstrProp.Ch[Cnt] <> Ch_None) Do begin case InstrProp.Ch[Cnt] Of @@ -2719,7 +2719,14 @@ end. { $Log$ - Revision 1.69 2004-09-26 17:45:30 peter + Revision 1.70 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.69 2004/09/26 17:45:30 peter * simple regvar support, not yet finished Revision 1.68 2004/06/20 08:55:31 florian diff --git a/compiler/i386/optbase.pas b/compiler/i386/optbase.pas index bb15ff1e7e..1ccaad72d6 100644 --- a/compiler/i386/optbase.pas +++ b/compiler/i386/optbase.pas @@ -28,49 +28,6 @@ unit optbase; interface -uses cpuinfo, cpubase; - - -{***************************************************************************** - Opcode propeties (needed for optimizer) -*****************************************************************************} - -{$ifndef NOOPT} -Type -{What an instruction can change} - TInsChange = (Ch_None, - {Read from a register} - Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI, - {write from a register} - Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI, - {read and write from/to a register} - Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI, - {modify the contents of a register with the purpose of using - this changed content afterwards (add/sub/..., but e.g. not rep - or movsd)} - Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI, - Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag}, - Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU, - Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1, - Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2, - Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3, - Ch_WMemEDI, - Ch_All - ); - - -const - MaxCh = 3; { Max things a instruction can change } -type - TInsProp = packed record - Ch : Array[1..MaxCh] of TInsChange; - end; - -const - InsProp : array[tasmop] of TInsProp = -{$i i386prop.inc} - -{$endif NOOPT} implementation @@ -79,7 +36,14 @@ end. { $Log$ - Revision 1.3 2004-06-20 08:55:31 florian + Revision 1.4 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.3 2004/06/20 08:55:31 florian * logs truncated } diff --git a/compiler/rgobj.pas b/compiler/rgobj.pas index 465af9a843..acf422ca80 100644 --- a/compiler/rgobj.pas +++ b/compiler/rgobj.pas @@ -135,8 +135,6 @@ unit rgobj; trgobj=class preserved_by_proc : tcpuregisterset; used_in_proc : tcpuregisterset; -// is_reg_var : Tsuperregisterset; {old regvars} -// reg_var_loaded:Tsuperregisterset; {old regvars} constructor create(Aregtype:Tregistertype; Adefaultsub:Tsubregister; @@ -170,25 +168,12 @@ unit rgobj; live_registers:Tsuperregisterworklist; { can be overriden to add cpu specific interferences } procedure add_cpu_interferences(p : tai);virtual; - function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai; - procedure forward_allocation(pfrom,pto:Tai); + procedure add_constraints(reg:Tregister);virtual; procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister); procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister); - procedure add_constraints(reg:Tregister);virtual; - function get_spill_subreg(r : tregister) : tsubregister;virtual; - procedure do_spill_read(list:Taasmoutput;instr:Taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo);virtual; - procedure do_spill_written(list:Taasmoutput;instr:Taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo);virtual; - procedure do_spill_readwritten(list:Taasmoutput;instr:Taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo);virtual; + procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual; + procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual; function instr_spill_register(list:Taasmoutput; instr:taicpu; @@ -603,22 +588,12 @@ unit rgobj; procedure trgobj.add_edges_used(u:Tsuperregister); var i:word; - v:tsuperregister; begin with live_registers do if length>0 then for i:=0 to length-1 do - begin - v:=buf^[i]; - add_edge(u,v); - { add also conflicts with all coalesced registers } - while ri_coalesced in reginfo[v].flags do - begin - v:=reginfo[v].alias; - add_edge(u,v); - end; - end; + add_edge(u,get_alias(buf^[i])); end; {$ifdef EXTDEBUG} @@ -1638,69 +1613,6 @@ unit rgobj; end; - function trgobj.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai; - var - back : Tsuperregisterworklist; - supreg : tsuperregister; - begin - back.copyfrom(live_registers); - result:=p; - while (p<>nil) and (p.typ=ait_regalloc) do - begin - supreg:=getsupreg(Tai_regalloc(p).reg); - {Rewind the register allocation.} - if (Tai_regalloc(p).ratype=ra_alloc) then - live_registers.delete(supreg) - else - begin - live_registers.add(supreg); - if supreg=huntfor1 then - begin - get_insert_pos:=Tai(p.previous); - back.done; - back.copyfrom(live_registers); - end; - if supreg=huntfor2 then - begin - get_insert_pos:=Tai(p.previous); - back.done; - back.copyfrom(live_registers); - end; - if supreg=huntfor3 then - begin - get_insert_pos:=Tai(p.previous); - back.done; - back.copyfrom(live_registers); - end; - end; - p:=Tai(p.previous); - end; - live_registers.done; - live_registers:=back; - end; - - - procedure trgobj.forward_allocation(pfrom,pto:Tai); - var - p : tai; - begin - {Forward the register allocation again.} - p:=pfrom; - while (p<>pto) do - begin - if p.typ<>ait_regalloc then - internalerror(200305311); - case Tai_regalloc(p).ratype of - ra_alloc : - live_registers.add(getsupreg(Tai_regalloc(p).reg)); - ra_dealloc : - live_registers.delete(getsupreg(Tai_regalloc(p).reg)); - end; - p:=Tai(p.next); - end; - end; - - function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean; { Returns true if any help registers have been used } var @@ -1790,65 +1702,22 @@ unit rgobj; end; - procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo); - - var helpins:Tai; - - begin - with regs[regidx] do - begin - helpins:=spilling_create_load(spilltemplist[orgreg],tempreg); - if pos=nil then - list.insertafter(helpins,list.first) - else - list.insertafter(helpins,pos.next); - ungetregisterinline(list,instr,tempreg); - forward_allocation(tai(helpins.next),instr); - end; - end; + procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister); + var + helpins : Tai; + begin + helpins:=spilling_create_load(spilltemp,tempreg); + list.insertbefore(helpins,instr); + end; - procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo); - - var helpins:Tai; - - begin - with regs[regidx] do - begin - helpins:=spilling_create_store(tempreg,spilltemplist[orgreg]); - list.insertafter(helpins,instr); - ungetregisterinline(list,helpins,tempreg); - end; - end; - - - procedure Trgobj.do_spill_readwritten(list:Taasmoutput;instr:taicpu; - pos:Tai;regidx:word; - const spilltemplist:Tspill_temp_list; - const regs:Tspillregsinfo); - - var helpins1,helpins2:Tai; - - begin - with regs[regidx] do - begin - helpins1:=spilling_create_load(spilltemplist[orgreg],tempreg); - if pos=nil then - list.insertafter(helpins1,list.first) - else - list.insertafter(helpins1,pos.next); - helpins2:=spilling_create_store(tempreg,spilltemplist[orgreg]); - list.insertafter(helpins2,instr); - ungetregisterinline(list,helpins2,tempreg); - forward_allocation(tai(helpins1.next),instr); - end; - end; + procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister); + var + helpins : Tai; + begin + helpins:=spilling_create_store(tempreg,spilltemp); + list.insertafter(helpins,instr); + end; function trgobj.get_spill_subreg(r : tregister) : tsubregister; @@ -1863,7 +1732,6 @@ unit rgobj; const spilltemplist:Tspill_temp_list): boolean; var counter, regindex: longint; - pos: tai; regs: tspillregsinfo; spilled: boolean; @@ -1874,7 +1742,7 @@ unit rgobj; begin tmpindex := regindex; supreg:=getsupreg(reg); - // did we already encounter this register? + { did we already encounter this register? } for i := 0 to pred(regindex) do if (regs[i].orgreg = supreg) then begin @@ -1887,7 +1755,7 @@ unit rgobj; regs[tmpindex].spillreg:=reg; if supregset_in(r,supreg) then begin - // add/update info on this register + { add/update info on this register } regs[tmpindex].mustbespilled := true; case operation of operand_read: @@ -1916,12 +1784,15 @@ unit rgobj; if (regs[i].mustbespilled) and (regs[i].orgreg=supreg) then begin - reg:=regs[i].tempreg; + { Only replace supreg } + setsupreg(reg,getsupreg(regs[i].tempreg)); break; end; end; - + var + counter2 : longint; + oldlive_registers : tsuperregisterworklist; begin result := false; fillchar(regs,sizeof(regs),0); @@ -1966,6 +1837,14 @@ unit rgobj; if not spilled then exit; + { Add conflicts with all non-spilled registers } + oldlive_registers.copyfrom(live_registers); + for counter2 := 0 to pred(regindex) do + begin + if (not regs[counter2].mustbespilled) then + live_registers.add(get_alias(regs[counter2].orgreg)); + end; + { generate the spilling code } result := true; for counter := 0 to pred(regindex) do @@ -1973,18 +1852,27 @@ unit rgobj; begin if mustbespilled then begin - pos:=get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg); - getregisterinline(list,pos,get_spill_subreg(regs[counter].spillreg),tempreg); + getregisterinline(list,tai(instr.previous),get_spill_subreg(regs[counter].spillreg),tempreg); + if regread then - if regwritten then - do_spill_readwritten(list,instr,pos,counter,spilltemplist,regs) - else - do_spill_read(list,instr,pos,counter,spilltemplist,regs) - else - do_spill_written(list,instr,pos,counter,spilltemplist,regs) + do_spill_read(list,instr,spilltemplist[orgreg],tempreg); + if regwritten then + do_spill_written(list,instr,spilltemplist[orgreg],tempreg); end; end; + { Release temp registers after all registers for the instruction are spilled } + for counter := 0 to pred(regindex) do + with regs[counter] do + begin + if mustbespilled then + ungetregisterinline(list,instr,tempreg); + end; + + { restore live registers } + live_registers.done; + live_registers:=oldlive_registers; + { substitute registers } for counter:=0 to instr.ops-1 do with instr.oper[counter]^ do @@ -2015,7 +1903,14 @@ unit rgobj; end. { $Log$ - Revision 1.137 2004-09-26 17:45:30 peter + Revision 1.138 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.137 2004/09/26 17:45:30 peter * simple regvar support, not yet finished Revision 1.136 2004/09/25 14:23:54 peter diff --git a/compiler/sparc/rgcpu.pas b/compiler/sparc/rgcpu.pas index a465efb3f1..75973c0fea 100644 --- a/compiler/sparc/rgcpu.pas +++ b/compiler/sparc/rgcpu.pas @@ -36,12 +36,8 @@ unit rgcpu; trgcpu=class(trgobj) procedure add_constraints(reg:tregister);override; function get_spill_subreg(r : tregister) : tsubregister;override; - procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; - procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; - procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; + procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override; + procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override; end; @@ -91,159 +87,89 @@ implementation end; - procedure trgcpu.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); + procedure trgcpu.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister); var - helpins: tai; - tmpref,ref : treference; + helpins : tai; + tmpref : treference; helplist : taasmoutput; - tmpreg : tregister; + hreg : tregister; begin - ref:=spilltemplist[regs[regidx].orgreg]; - if abs(ref.offset)>4095 then + if abs(spilltemp.offset)>4095 then begin helplist:=taasmoutput.create; - reference_reset(tmpref); - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - getregisterinline(helplist,nil,defaultsub,tmpreg) + if getregtype(tempreg)=R_INTREGISTER then + hreg:=tempreg else - tmpreg:=cg.getintregister(helplist,OS_ADDR); + hreg:=cg.getintregister(helplist,OS_ADDR); - tmpref.offset:=ref.offset; + reference_reset(tmpref); + tmpref.offset:=spilltemp.offset; tmpref.refaddr:=addr_hi; - helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg)); + helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg)); tmpref.refaddr:=addr_lo; - helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg)); + helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg)); - if ref.index<>NR_NO then - internalerror(200401263); - ref.index:=tmpreg; - ref.offset:=0; + reference_reset_base(tmpref,hreg,0); - helpins:=spilling_create_load(ref,regs[regidx].tempreg); + helpins:=spilling_create_load(spilltemp,tempreg); helplist.concat(helpins); - if pos=nil then - list.insertlistafter(list.first,helplist) - else - list.insertlistafter(pos.next,helplist); - helplist.free; - - ungetregisterinline(list,helpins,regs[regidx].tempreg); - - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - ungetregisterinline(list,helpins,tmpreg); - - forward_allocation(tai(helpins.next),instr); + list.insertlistbefore(instr,helplist) end else - inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs); + inherited do_spill_read(list,instr,spilltemp,tempreg); end; - procedure trgcpu.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); + procedure trgcpu.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister); var - helpins: tai; - ref,tmpref : treference; + helpins : tai; + tmpref : treference; helplist : taasmoutput; - tmpreg : tregister; + hreg : tregister; begin - ref:=spilltemplist[regs[regidx].orgreg]; - if abs(ref.offset)>4095 then + if abs(spilltemp.offset)>4095 then begin helplist:=taasmoutput.create; - reference_reset(tmpref); - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - getregisterinline(helplist,pos,defaultsub,tmpreg) + if getregtype(tempreg)=R_INTREGISTER then + getregisterinline(helplist,tai(helplist.first),R_SUBWHOLE,hreg) else - tmpreg:=cg.getintregister(helplist,OS_ADDR); + hreg:=cg.getintregister(helplist,OS_ADDR); - tmpref.offset:=ref.offset; + reference_reset(tmpref); + tmpref.offset:=spilltemp.offset; tmpref.refaddr:=addr_hi; - helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg)); + helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg)); tmpref.refaddr:=addr_lo; - helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg)); + helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg)); - if ref.index<>NR_NO then - internalerror(200401263); - ref.index:=tmpreg; - ref.offset:=0; + reference_reset_base(tmpref,hreg,0); - helpins:=spilling_create_store(regs[regidx].tempreg,ref); + helpins:=spilling_create_store(tempreg,spilltemp); helplist.concat(helpins); - list.insertlistafter(instr,helplist); - helplist.free; + if getregtype(tempreg)=R_INTREGISTER then + ungetregisterinline(helplist,tai(helplist.last),hreg); - ungetregisterinline(list,helpins,regs[regidx].tempreg); - - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - ungetregisterinline(list,helpins,tmpreg); + list.insertlistafter(instr,helplist) end else - inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs); - end; - - - procedure trgcpu.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; - const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); - var - helpins1, helpins2: tai; - tmpref,ref : treference; - helplist : taasmoutput; - tmpreg : tregister; - begin - ref:=spilltemplist[regs[regidx].orgreg]; - if abs(ref.offset)>4095 then - begin - helplist:=taasmoutput.create; - reference_reset(tmpref); - - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - getregisterinline(helplist,nil,defaultsub,tmpreg) - else - tmpreg:=cg.getintregister(helplist,OS_ADDR); - - tmpref.offset:=ref.offset; - tmpref.refaddr:=addr_hi; - helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg)); - - tmpref.refaddr:=addr_lo; - helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg)); - - if ref.index<>NR_NO then - internalerror(200401263); - ref.index:=tmpreg; - ref.offset:=0; - - helpins1:=spilling_create_load(ref,regs[regidx].tempreg); - helplist.concat(helpins1); - if pos=nil then - list.insertlistafter(list.first,helplist) - else - list.insertlistafter(pos.next,helplist); - helplist.free; - - helpins2:=spilling_create_store(regs[regidx].tempreg,ref); - list.insertafter(helpins2,instr); - ungetregisterinline(list,helpins2,regs[regidx].tempreg); - - if getregtype(regs[regidx].tempreg)=R_INTREGISTER then - ungetregisterinline(list,helpins2,tmpreg); - - forward_allocation(tai(helpins1.next),instr); - end - else - inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs); - end; + inherited do_spill_written(list,instr,spilltemp,tempreg); + end; end. { $Log$ - Revision 1.27 2004-10-01 17:33:47 peter + Revision 1.28 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.27 2004/10/01 17:33:47 peter * indents Revision 1.26 2004/09/28 20:19:36 peter diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index 6f8400239b..a5d196f597 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -130,6 +130,36 @@ interface instabentries = {$i i386nop.inc} {$endif x86_64} maxinfolen = 8; + MaxInsChanges = 3; { Max things a instruction can change } + + type + { What an instruction can change. Needed for optimizer and spilling code } + TInsChange = (Ch_None, + {Read from a register} + Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI, + {write from a register} + Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI, + {read and write from/to a register} + Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI, + {modify the contents of a register with the purpose of using + this changed content afterwards (add/sub/..., but e.g. not rep + or movsd)} + Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI, + Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag}, + Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU, + Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1, + Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2, + Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3, + Ch_WMemEDI, + Ch_All + ); + + TInsProp = packed record + Ch : Array[1..MaxInsChanges] of TInsChange; + end; + + const + InsProp : array[tasmop] of TInsProp = {$i i386prop.inc} type TOperandOrder = (op_intel,op_att); @@ -201,6 +231,8 @@ interface procedure Pass2(objdata:TAsmObjectdata);virtual; procedure SetOperandOrder(order:TOperandOrder); function is_same_reg_move(regtype: Tregistertype):boolean;override; + { register spilling code } + function spilling_get_operation_type(opnr: longint): topertype;override; protected procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override; procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override; @@ -366,6 +398,12 @@ implementation ); {$endif x86_64} + { Operation type for spilling code } + type + toperation_type_table=array[tasmop,0..Max_Operands] of topertype; + var + operation_type_table : ^toperation_type_table; + {**************************************************************************** TAI_ALIGN @@ -1932,15 +1970,74 @@ implementation end; + procedure build_spilling_operation_type_table; + var + opcode : tasmop; + i : integer; + begin + new(operation_type_table); + fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read)); + for opcode:=low(tasmop) to high(tasmop) do + begin + for i:=1 to MaxInsChanges do + begin + case InsProp[opcode].Ch[i] of + Ch_Rop1 : + operation_type_table^[opcode,0]:=operand_read; + Ch_Wop1 : + operation_type_table^[opcode,0]:=operand_write; + Ch_RWop1, + Ch_Mop1 : + operation_type_table^[opcode,0]:=operand_readwrite; + Ch_Rop2 : + operation_type_table^[opcode,1]:=operand_read; + Ch_Wop2 : + operation_type_table^[opcode,1]:=operand_write; + Ch_RWop2, + Ch_Mop2 : + operation_type_table^[opcode,1]:=operand_readwrite; + Ch_Rop3 : + operation_type_table^[opcode,2]:=operand_read; + Ch_Wop3 : + operation_type_table^[opcode,2]:=operand_write; + Ch_RWop3, + Ch_Mop3 : + operation_type_table^[opcode,2]:=operand_readwrite; + end; + end; + end; + end; + + + function taicpu.spilling_get_operation_type(opnr: longint): topertype; + begin + result:=operation_type_table^[opcode,opnr]; + end; + + function spilling_create_load(const ref:treference;r:tregister): tai; begin - internalerror(200406131); + case getregtype(r) of + R_INTREGISTER : + result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r); + R_MMREGISTER : + result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r); + else + internalerror(200401041); + end; end; function spilling_create_store(r:tregister; const ref:treference): tai; begin - internalerror(200406132); + case getregtype(r) of + R_INTREGISTER : + result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref); + R_MMREGISTER : + result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref); + else + internalerror(200401041); + end; end; @@ -1970,6 +2067,7 @@ implementation procedure InitAsm; begin + build_spilling_operation_type_table; {$ifndef NOAG386BIN} if not assigned(instabcache) then BuildInsTabCache; @@ -1979,12 +2077,17 @@ implementation procedure DoneAsm; begin + if assigned(operation_type_table) then + begin + dispose(operation_type_table); + operation_type_table:=nil; + end; {$ifndef NOAG386BIN} if assigned(instabcache) then - begin - dispose(instabcache); - instabcache:=nil; - end; + begin + dispose(instabcache); + instabcache:=nil; + end; {$endif NOAG386BIN} end; @@ -1995,7 +2098,14 @@ begin end. { $Log$ - Revision 1.58 2004-09-27 15:12:47 peter + Revision 1.59 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.58 2004/09/27 15:12:47 peter * IE when expecting top_ref Revision 1.57 2004/06/20 08:55:32 florian diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index 62f796610a..845c70644e 100644 --- a/compiler/x86/cgx86.pas +++ b/compiler/x86/cgx86.pas @@ -551,11 +551,14 @@ unit cgx86; if s in [S_BL,S_WL,S_L] then reg2:=makeregsize(list,reg2,OS_32); {$endif x86_64} - instr:=taicpu.op_reg_reg(op,s,reg1,reg2); - { Notify the register allocator that we have written a move instruction so - it can try to eliminate it. } - add_move_instruction(instr); - list.concat(instr); + if (reg1<>reg2) then + begin + instr:=taicpu.op_reg_reg(op,s,reg1,reg2); + { Notify the register allocator that we have written a move instruction so + it can try to eliminate it. } + add_move_instruction(instr); + list.concat(instr); + end; end; @@ -1672,7 +1675,14 @@ unit cgx86; end. { $Log$ - Revision 1.126 2004-10-03 12:42:22 florian + Revision 1.127 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.126 2004/10/03 12:42:22 florian * made sqrt, sqr and abs internal for the sparc Revision 1.125 2004/09/25 14:23:55 peter diff --git a/compiler/x86/rgx86.pas b/compiler/x86/rgx86.pas index d40eac52ed..ade0955998 100644 --- a/compiler/x86/rgx86.pas +++ b/compiler/x86/rgx86.pas @@ -36,10 +36,21 @@ unit rgx86; type trgx86 = class(trgobj) +{$ifdef OLDRGX86} function instr_spill_register(list:Taasmoutput; instr:taicpu; const r:Tsuperregisterset; const spilltemplist:Tspill_temp_list): boolean;override; +{$endif OLDRGX86} + function get_spill_subreg(r : tregister) : tsubregister;override; +{ + procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; + procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; + procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; +} end; tpushedsavedloc = record @@ -107,6 +118,7 @@ implementation Trgcpu ******************************************************************************} +{$ifdef OLDRGX86} function trgx86.instr_spill_register(list:Taasmoutput; instr:taicpu; const r:Tsuperregisterset; @@ -485,8 +497,67 @@ implementation end; end; end; +{$endif OLDRGX86} + function trgx86.get_spill_subreg(r : tregister) : tsubregister; + begin + result:=getsubreg(r); + end; + + + (* + procedure trgx86.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); + var + helpins: tai; + tmpref,ref : treference; + helplist : taasmoutput; + tmpreg : tregister; + begin +{ ref:=spilltemplist[regs[regidx].orgreg]; + if abs(ref.offset)>4095 then + begin + end + else } + inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs); + end; + + + procedure trgx86.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); + var + helpins: tai; + ref,tmpref : treference; + helplist : taasmoutput; + tmpreg : tregister; + begin +{ ref:=spilltemplist[regs[regidx].orgreg]; + if abs(ref.offset)>4095 then + begin + end + else } + inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs); + end; + + + procedure trgx86.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; + const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo); + var + helpins1, helpins2: tai; + tmpref,ref : treference; + helplist : taasmoutput; + tmpreg : tregister; + begin +{ ref:=spilltemplist[regs[regidx].orgreg]; + if abs(ref.offset)>4095 then + begin + end + else } + inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs); + end; +*) + {****************************************************************************** Trgx86fpu ******************************************************************************} @@ -619,7 +690,14 @@ implementation end. { $Log$ - Revision 1.6 2004-09-27 14:49:45 peter + Revision 1.7 2004-10-04 20:46:22 peter + * spilling code rewritten for x86. It now used the generic + spilling routines. Special x86 optimization still needs + to be added. + * Spilling fixed when both operands needed to be spilled + * Cleanup of spilling routine, do_spill_readwritten removed + + Revision 1.6 2004/09/27 14:49:45 peter * handle 3 operand opcodes the same as 2 operand opcodes, the third operand can only be a const or register CL, so it doesn't affect spilling