+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)

* more fixes to m68k for 64-bit operations
This commit is contained in:
carl 2002-08-19 18:17:47 +00:00
parent d709f6720b
commit ed77671a9b
5 changed files with 302 additions and 33 deletions

View File

@ -72,6 +72,13 @@ unit cg64f32;
procedure a_param64_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override;
procedure a_param64_loc(list : taasmoutput;const l : tlocation;const locpara : tparalocation);override;
{# This routine tries to optimize the a_op64_const_reg operation, by
removing superfluous opcodes. Returns TRUE if normal processing
must continue in op64_const_reg, otherwise, everything is processed
entirely in this routine, by emitting the appropriate 32-bit opcodes.
}
function optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;override;
procedure g_rangecheck64(list: taasmoutput; const p: tnode;
const todef: tdef); override;
end;
@ -620,6 +627,98 @@ unit cg64f32;
end;
end;
function tcg64f32.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;
var
lowvalue, highvalue : cardinal;
hreg: tregister;
begin
lowvalue := cardinal(a);
highvalue:= a shr 32;
{ assume it will be optimized out }
optimize64_op_const_reg := true;
case op of
OP_ADD:
begin
if a = 0 then
exit;
end;
OP_AND:
begin
if lowvalue <> high(cardinal) then
cg.a_op_const_reg(list,op,lowvalue,reg.reglo);
if highvalue <> high(cardinal) then
cg.a_op_const_reg(list,op,highvalue,reg.reghi);
{ already emitted correctly }
exit;
end;
OP_OR:
begin
if lowvalue <> 0 then
cg.a_op_const_reg(list,op,lowvalue,reg.reglo);
if highvalue <> 0 then
cg.a_op_const_reg(list,op,highvalue,reg.reghi);
{ already emitted correctly }
exit;
end;
OP_SUB:
begin
if a = 0 then
exit;
end;
OP_XOR:
begin
end;
OP_SHL:
begin
if a = 0 then
exit;
{ simply clear low-register
and shift the rest and swap
registers.
}
if (a > 31) then
begin
cg.a_load_const_reg(list,OS_32,0,reg.reglo);
cg.a_op_const_reg(list,OP_SHL,a mod 32,reg.reghi);
{ swap the registers }
hreg := reg.reghi;
reg.reghi := reg.reglo;
reg.reglo := hreg;
exit;
end;
end;
OP_SHR:
begin
if a = 0 then exit;
{ simply clear high-register
and shift the rest and swap
registers.
}
if (a > 31) then
begin
cg.a_load_const_reg(list,OS_32,0,reg.reghi);
cg.a_op_const_reg(list,OP_SHL,a mod 32,reg.reglo);
{ swap the registers }
hreg := reg.reghi;
reg.reghi := reg.reglo;
reg.reglo := hreg;
exit;
end;
end;
OP_IMUL,OP_MUL:
begin
if a = 1 then exit;
end;
OP_IDIV,OP_DIV:
begin
if a = 1 then exit;
end;
else
internalerror(20020817);
end;
optimize64_op_const_reg := false;
end;
(*
procedure int64f32_assignment_int64_reg(p : passignmentnode);
@ -633,7 +732,11 @@ begin
end.
{
$Log$
Revision 1.26 2002-08-17 22:09:43 florian
Revision 1.27 2002-08-19 18:17:47 carl
+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
* more fixes to m68k for 64-bit operations
Revision 1.26 2002/08/17 22:09:43 florian
* result type handling in tcgcal.pass_2 overhauled
* better tnode.dowrite
* some ppc stuff fixed

View File

@ -173,6 +173,12 @@ unit cg64f64;
const todef: tdef);
begin
end;
function tcg64f64.optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;
begin
{ this should be the same routine as optimize_const_reg!!!!!!!! }
end;
procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister64);
@ -190,7 +196,11 @@ unit cg64f64;
end.
{
$Log$
Revision 1.3 2002-08-17 22:09:43 florian
Revision 1.4 2002-08-19 18:17:48 carl
+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
* more fixes to m68k for 64-bit operations
Revision 1.3 2002/08/17 22:09:43 florian
* result type handling in tcgcal.pass_2 overhauled
* better tnode.dowrite
* some ppc stuff fixed

View File

@ -248,13 +248,15 @@ unit cgobj;
This routine tries to optimize the const_reg opcode, and should be
called at the start of a_op_const_reg. It returns the actual opcode
to emit, and the constant value to emit. If this routine returns
FALSE, no instruction should be emitted (.eg : imul reg by 1 )
TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
@param(op The opcode to emit, returns the opcode which must be emitted)
@param(a The constant which should be emitted, returns the constant which must
be amitted)
}
function optimize_const_reg(var op: topcg; var a : aword): boolean;virtual;
be emitted)
@param(reg The register to emit the opcode with, returns the register with
which the opcode will be emitted)
}
function optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aword; var reg: tregister): boolean;virtual;
{#
This routine is used in exception management nodes. It should
@ -447,6 +449,19 @@ unit cgobj;
procedure a_param64_ref(list : taasmoutput;const r : treference;const loc : tparalocation);virtual;abstract;
procedure a_param64_loc(list : taasmoutput;const l : tlocation;const loc : tparalocation);virtual;abstract;
{
This routine tries to optimize the const_reg opcode, and should be
called at the start of a_op64_const_reg. It returns the actual opcode
to emit, and the constant value to emit. If this routine returns
TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
@param(op The opcode to emit, returns the opcode which must be emitted)
@param(a The constant which should be emitted, returns the constant which must
be emitted)
@param(reg The register to emit the opcode with, returns the register with
which the opcode will be emitted)
}
function optimize64_op_const_reg(list: taasmoutput; var op: topcg; var a : qword; var reg: tregister64): boolean;virtual;abstract;
{ override to catch 64bit rangechecks }
@ -756,21 +771,21 @@ unit cgobj;
end;
function tcg.optimize_const_reg(var op: topcg; var a : aword): boolean;
function tcg.optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aword; var reg:tregister): boolean;
var
powerval : longint;
begin
optimize_const_reg := true;
optimize_op_const_reg := false;
case op of
{ or with zero returns same result }
OP_OR : if a = 0 then optimize_const_reg := false;
OP_OR : if a = 0 then optimize_op_const_reg := true;
{ and with max returns same result }
OP_AND : if (a = high(a)) then optimize_const_reg := false;
OP_AND : if (a = high(a)) then optimize_op_const_reg := true;
{ division by 1 returns result }
OP_DIV :
begin
if a = 1 then
optimize_const_reg := false
optimize_op_const_reg := true
else if ispowerof2(int64(a), powerval) then
begin
a := powerval;
@ -781,7 +796,7 @@ unit cgobj;
OP_IDIV:
begin
if a = 1 then
optimize_const_reg := false
optimize_op_const_reg := true
else if ispowerof2(int64(a), powerval) then
begin
a := powerval;
@ -792,7 +807,7 @@ unit cgobj;
OP_MUL,OP_IMUL:
begin
if a = 1 then
optimize_const_reg := false
optimize_op_const_reg := true
else if ispowerof2(int64(a), powerval) then
begin
a := powerval;
@ -802,8 +817,8 @@ unit cgobj;
end;
OP_SAR,OP_SHL,OP_SHR:
begin
if a = 1 then
optimize_const_reg := false;
if a = 0 then
optimize_op_const_reg := true;
exit;
end;
end;
@ -1553,7 +1568,11 @@ finalization
end.
{
$Log$
Revision 1.52 2002-08-17 22:09:43 florian
Revision 1.53 2002-08-19 18:17:48 carl
+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
* more fixes to m68k for 64-bit operations
Revision 1.52 2002/08/17 22:09:43 florian
* result type handling in tcgcal.pass_2 overhauled
* better tnode.dowrite
* some ppc stuff fixed

View File

@ -38,7 +38,11 @@
{
$Log$
Revision 1.5 2002-08-15 15:11:53 carl
Revision 1.6 2002-08-19 18:17:48 carl
+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
* more fixes to m68k for 64-bit operations
Revision 1.5 2002/08/15 15:11:53 carl
* oldset define is now correct for all cpu's except i386
* correct compilation problems because of the above
@ -50,3 +54,6 @@
+ log added
}
{
}

View File

@ -30,7 +30,7 @@ unit cgcpu;
cginfo,cgbase,cgobj,
aasmbase,aasmtai,aasmcpu,
cpubase,cpuinfo,cpupara,
node,symconst;
node,symconst,cg64f32;
type
tcg68k = class(tcg)
@ -61,13 +61,7 @@ unit cgcpu;
{ generates overflow checking code for a node }
procedure g_overflowcheck(list: taasmoutput; const p: tnode); override;
procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer); override;
{
This routine should setup the stack frame and allocate @var(localsize) bytes on
the local stack (for local variables). It should also setup the frame pointer,
so that all variables are now accessed via the frame pointer register.
}
procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
{ restores the previous frame pointer at procedure exit }
procedure g_restore_frame_pointer(list : taasmoutput);override;
procedure g_return_from_proc(list : taasmoutput;parasize : aword);override;
procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
@ -85,6 +79,10 @@ unit cgcpu;
end;
tcg64f68k = class(tcg64f32)
procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override;
end;
{ This function returns true if the reference+offset is valid.
Otherwise extra code must be generated to solve the reference.
@ -110,7 +108,7 @@ Implementation
uses
globtype,globals,verbose,systems,cutils,
symdef,symsym,defbase,paramgr,
rgobj,tgobj,rgcpu,cg64f32;
rgobj,tgobj,rgcpu;
const
@ -168,7 +166,9 @@ Implementation
end;
end;
{****************************************************************************}
{ TCG68K }
{****************************************************************************}
function tcg68k.fixref(list: taasmoutput; var ref: treference): boolean;
var
@ -285,7 +285,11 @@ Implementation
procedure tcg68k.a_loadfpu_reg_reg(list: taasmoutput; reg1, reg2: tregister);
begin
list.concat(taicpu.op_reg_reg(A_FMOVE,S_FD,reg1,reg2));
{ in emulation mode, only 32-bit single is supported }
if cs_fp_emulation in aktmoduleswitches then
list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
else
list.concat(taicpu.op_reg_reg(A_FMOVE,S_FD,reg1,reg2));
end;
@ -299,7 +303,11 @@ Implementation
if opsize = S_FX then
internalerror(20020729);
fixref(list,href);
list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
{ in emulation mode, only 32-bit single is supported }
if cs_fp_emulation in aktmoduleswitches then
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
else
list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
end;
procedure tcg68k.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
@ -310,7 +318,11 @@ Implementation
{ extended is not supported, since it is not available on Coldfire }
if opsize = S_FX then
internalerror(20020729);
list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
{ in emulation mode, only 32-bit single is supported }
if cs_fp_emulation in aktmoduleswitches then
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
else
list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
end;
procedure tcg68k.a_loadmm_reg_reg(list: taasmoutput; reg1, reg2: tregister);
@ -341,7 +353,7 @@ Implementation
opcode : tasmop;
begin
{ need to emit opcode? }
if not optimize_const_reg(op, a) then
if optimize_op_const_reg(list, op, a, reg) then
exit;
opcode := topcg2tasmop[op];
case op of
@ -1100,15 +1112,133 @@ Implementation
list.concat(ai);
end;
{****************************************************************************}
{ TCG64F68K }
{****************************************************************************}
procedure tcg64f68k.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
var
hreg1, hreg2 : tregister;
opcode : tasmop;
begin
opcode := topcg2tasmop[op];
case op of
OP_ADD :
begin
{ if one of these three registers is an address
register, we'll really get into problems!
}
if rg.isaddressregister(regdst.reglo) or
rg.isaddressregister(regdst.reghi) or
rg.isaddressregister(regsrc.reghi) then
internalerror(20020817);
list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
end;
OP_AND,OP_OR :
begin
{ at least one of the registers must be a data register }
if (rg.isaddressregister(regdst.reglo) and
rg.isaddressregister(regsrc.reglo)) or
(rg.isaddressregister(regsrc.reghi) and
rg.isaddressregister(regdst.reghi))
then
internalerror(20020817);
cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
end;
{ this is handled in 1st pass for 32-bit cpu's (helper call) }
OP_IDIV,OP_DIV,
OP_IMUL,OP_MUL: internalerror(2002081701);
{ this is also handled in 1st pass for 32-bit cpu's (helper call) }
OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
OP_SUB:
begin
{ if one of these three registers is an address
register, we'll really get into problems!
}
if rg.isaddressregister(regdst.reglo) or
rg.isaddressregister(regdst.reghi) or
rg.isaddressregister(regsrc.reghi) then
internalerror(20020817);
list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
end;
OP_XOR:
begin
if rg.isaddressregister(regdst.reglo) or
rg.isaddressregister(regsrc.reglo) or
rg.isaddressregister(regsrc.reghi) or
rg.isaddressregister(regdst.reghi) then
internalerror(20020817);
list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
end;
end; { end case }
end;
procedure tcg64f68k.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
var
lowvalue : cardinal;
highvalue : cardinal;
begin
{ is it optimized out ? }
if optimize64_op_const_reg(list,op,value,reg) then
exit;
lowvalue := cardinal(value);
highvalue:= value shr 32;
{ the destination registers must be data registers }
if rg.isaddressregister(reg.reglo) or
rg.isaddressregister(reg.reghi) then
internalerror(20020817);
case op of
OP_ADD :
begin
list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,reg.reglo));
list.concat(taicpu.op_const_reg(A_ADDX,S_L,highvalue,reg.reglo));
end;
OP_AND :
begin
{ should already be optimized out }
internalerror(2002081801);
end;
OP_OR :
begin
{ should already be optimized out }
internalerror(2002081802);
end;
{ this is handled in 1st pass for 32-bit cpu's (helper call) }
OP_IDIV,OP_DIV,
OP_IMUL,OP_MUL: internalerror(2002081701);
{ this is also handled in 1st pass for 32-bit cpu's (helper call) }
OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
OP_SUB:
begin
list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,reg.reglo));
list.concat(taicpu.op_const_reg(A_SUBX,S_L,highvalue,reg.reglo));
end;
OP_XOR:
begin
list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,reg.reglo));
list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,reg.reglo));
end;
end; { end case }
end;
begin
cg := tcg68k.create;
cg64 :=tcg64f32.create;
cg64 :=tcg64f68k.create;
end.
{
$Log$
Revision 1.4 2002-08-16 14:24:59 carl
Revision 1.5 2002-08-19 18:17:48 carl
+ optimize64_op_const_reg implemented (optimizes 64-bit constant opcodes)
* more fixes to m68k for 64-bit operations
Revision 1.4 2002/08/16 14:24:59 carl
* issameref() to test if two references are the same (then emit no opcodes)
+ ret_in_reg to replace ret_in_acc
(fix some register allocation bugs at the same time)