mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-10 15:31:14 +02:00
+ implemented the in_neg_assign_x and in_not_assign_x inline nodes, which will
be used (TBD in a future commit) for optimizing x:=-x and x:=not x on CPUs that support performing these operations directly in memory (such as x86) git-svn-id: trunk@35749 -
This commit is contained in:
parent
8024fcd7ec
commit
256dc546ac
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -11572,6 +11572,7 @@ tests/test/cg/tmoddiv1.pp svneol=native#text/plain
|
||||
tests/test/cg/tmoddiv2.pp svneol=native#text/plain
|
||||
tests/test/cg/tmul3264.pp svneol=native#text/plain
|
||||
tests/test/cg/tneg.pp svneol=native#text/plain
|
||||
tests/test/cg/tnegnotassign1.pp svneol=native#text/plain
|
||||
tests/test/cg/tnot.pp svneol=native#text/plain
|
||||
tests/test/cg/tobjsiz2.pp svneol=native#text/plain
|
||||
tests/test/cg/tobjsize.pp svneol=native#text/plain
|
||||
@ -11602,6 +11603,7 @@ tests/test/cg/ttryfin5.pp svneol=native#text/plain
|
||||
tests/test/cg/tumin.pp svneol=native#text/plain
|
||||
tests/test/cg/tvec.pp svneol=native#text/plain
|
||||
tests/test/cg/uandorxorassign.pp svneol=native#text/plain
|
||||
tests/test/cg/unegnotassign.pp svneol=native#text/plain
|
||||
tests/test/cg/uprintf3.pp svneol=native#text/plain
|
||||
tests/test/cg/variants/ivarol10.pp svneol=native#text/plain
|
||||
tests/test/cg/variants/ivarol100.pp svneol=native#text/plain
|
||||
|
@ -739,7 +739,10 @@ unit cg64f32;
|
||||
tempreg.reghi:=cg.getintregister(list,OS_32);
|
||||
tempreg.reglo:=cg.getintregister(list,OS_32);
|
||||
a_load64_ref_reg(list,ref,tempreg);
|
||||
a_op64_reg_reg(list,op,size,reg,tempreg);
|
||||
if op in [OP_NEG,OP_NOT] then
|
||||
a_op64_reg_reg(list,op,size,tempreg,tempreg)
|
||||
else
|
||||
a_op64_reg_reg(list,op,size,reg,tempreg);
|
||||
a_load64_reg_ref(list,tempreg,ref);
|
||||
end;
|
||||
|
||||
|
@ -101,10 +101,9 @@ const
|
||||
in_shl_assign_x_y = 90;
|
||||
in_shr_assign_x_y = 91;
|
||||
in_rol_assign_x_y = 92;
|
||||
in_ror_assign_x_y = 93;
|
||||
in_ror_assign_x_y = 93;}
|
||||
in_neg_assign_x = 94;
|
||||
in_not_assign_x = 95;
|
||||
}
|
||||
|
||||
{ Internal constant functions }
|
||||
in_const_sqr = 100;
|
||||
|
@ -662,21 +662,42 @@ unit cgcpu;
|
||||
op1,op2 : TAsmOp;
|
||||
tempref : treference;
|
||||
begin
|
||||
if not(op in [OP_NEG,OP_NOT]) then
|
||||
begin
|
||||
get_64bit_ops(op,op1,op2);
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
if op in [OP_ADD,OP_SUB] then
|
||||
case op of
|
||||
OP_NOT:
|
||||
begin
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
|
||||
inc(tempref.offset,4);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
|
||||
end;
|
||||
OP_NEG:
|
||||
begin
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
inc(tempref.offset,4);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_L,tempref));
|
||||
cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
|
||||
list.concat(taicpu.op_reg_ref(op1,S_L,reg.reglo,tempref));
|
||||
inc(tempref.offset,4);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_L,reg.reghi,tempref));
|
||||
if op in [OP_ADD,OP_SUB] then
|
||||
dec(tempref.offset,4);
|
||||
list.concat(taicpu.op_ref(A_NEG,S_L,tempref));
|
||||
inc(tempref.offset,4);
|
||||
list.concat(taicpu.op_const_ref(A_SBB,S_L,-1,tempref));
|
||||
cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
|
||||
end
|
||||
else
|
||||
inherited;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
get_64bit_ops(op,op1,op2);
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
if op in [OP_ADD,OP_SUB] then
|
||||
cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
|
||||
list.concat(taicpu.op_reg_ref(op1,S_L,reg.reglo,tempref));
|
||||
inc(tempref.offset,4);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_L,reg.reghi,tempref));
|
||||
if op in [OP_ADD,OP_SUB] then
|
||||
cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -1011,7 +1011,8 @@ unit cgcpu;
|
||||
begin
|
||||
tmpref:=ref;
|
||||
make_simple_ref(list,tmpref);
|
||||
check_register_size(size,reg);
|
||||
if not (op in [OP_NEG,OP_NOT]) then
|
||||
check_register_size(size,reg);
|
||||
|
||||
if size in [OS_64, OS_S64] then
|
||||
internalerror(2013050803);
|
||||
@ -2593,21 +2594,52 @@ unit cgcpu;
|
||||
op1,op2 : TAsmOp;
|
||||
tempref : treference;
|
||||
begin
|
||||
if not(op in [OP_NEG,OP_NOT]) then
|
||||
begin
|
||||
get_64bit_ops(op,op1,op2);
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reglo),tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reghi),tempref));
|
||||
end
|
||||
else
|
||||
inherited;
|
||||
case op of
|
||||
OP_NOT:
|
||||
begin
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
end;
|
||||
OP_NEG:
|
||||
begin
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
inc(tempref.offset,6);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
dec(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
dec(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
|
||||
dec(tempref.offset,2);
|
||||
list.concat(taicpu.op_ref(A_NEG,S_W,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
|
||||
end;
|
||||
else
|
||||
begin
|
||||
get_64bit_ops(op,op1,op2);
|
||||
tempref:=ref;
|
||||
tcgx86(cg).make_simple_ref(list,tempref);
|
||||
list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reglo),tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
|
||||
inc(tempref.offset,2);
|
||||
list.concat(taicpu.op_reg_ref(op2,S_W,GetNextReg(reg.reghi),tempref));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -36,6 +36,7 @@ interface
|
||||
procedure second_predsucc;virtual;
|
||||
procedure second_incdec;virtual;
|
||||
procedure second_AndOrXor_assign;virtual;
|
||||
procedure second_NegNot_assign;virtual;
|
||||
procedure second_typeinfo;virtual;
|
||||
procedure second_includeexclude;virtual;
|
||||
procedure second_pi; virtual;
|
||||
@ -204,6 +205,9 @@ implementation
|
||||
in_or_assign_x_y,
|
||||
in_xor_assign_x_y:
|
||||
second_AndOrXor_assign;
|
||||
in_neg_assign_x,
|
||||
in_not_assign_x:
|
||||
second_NegNot_assign;
|
||||
else internalerror(9);
|
||||
end;
|
||||
end;
|
||||
@ -493,6 +497,29 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
NEG/NOT ASSIGN GENERIC HANDLING
|
||||
*****************************************************************************}
|
||||
procedure tcginlinenode.second_NegNot_assign;
|
||||
const
|
||||
negnotop:array[in_neg_assign_x..in_not_assign_x] of TOpCG=(OP_NEG,OP_NOT);
|
||||
{$ifndef cpu64bitalu}
|
||||
var
|
||||
NR_NO64: tregister64=(reglo:NR_NO;reghi:NR_NO);
|
||||
{$endif not cpu64bitalu}
|
||||
begin
|
||||
{ load parameter, must be a reference }
|
||||
secondpass(left);
|
||||
|
||||
{$ifndef cpu64bitalu}
|
||||
if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
|
||||
cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],def_cgsize(left.resultdef),NR_NO64,left.location)
|
||||
else
|
||||
{$endif not cpu64bitalu}
|
||||
hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,negnotop[inlinenumber],left.resultdef,NR_NO,left.location);
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TYPEINFO GENERIC HANDLING
|
||||
*****************************************************************************}
|
||||
|
@ -91,6 +91,7 @@ interface
|
||||
function first_sar: tnode; virtual;
|
||||
function first_fma : tnode; virtual;
|
||||
function first_AndOrXor_assign: tnode; virtual;
|
||||
function first_NegNot_assign: tnode; virtual;
|
||||
private
|
||||
function handle_str: tnode;
|
||||
function handle_reset_rewrite_typed: tnode;
|
||||
@ -3067,6 +3068,34 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
in_neg_assign_x,
|
||||
in_not_assign_x:
|
||||
begin
|
||||
resultdef:=voidtype;
|
||||
if not(df_generic in current_procinfo.procdef.defoptions) then
|
||||
begin
|
||||
valid_for_var(left,true);
|
||||
set_varstate(left,vs_readwritten,[vsf_must_be_valid]);
|
||||
|
||||
if is_integer(left.resultdef) then
|
||||
begin
|
||||
{ value of left gets changed -> must be unique }
|
||||
set_unique(left);
|
||||
{ these nodes shouldn't be created, when range checking is on }
|
||||
if [cs_check_range,cs_check_overflow]*current_settings.localswitches<>[] then
|
||||
internalerror(2017040703);
|
||||
end
|
||||
{ generic type parameter? }
|
||||
else if is_typeparam(left.resultdef) then
|
||||
begin
|
||||
result:=cnothingnode.create;
|
||||
exit;
|
||||
end
|
||||
else
|
||||
CGMessagePos(left.fileinfo,type_e_ordinal_expr_expected);
|
||||
end;
|
||||
end;
|
||||
|
||||
in_read_x,
|
||||
in_readln_x,
|
||||
in_readstr_x,
|
||||
@ -3597,6 +3626,12 @@ implementation
|
||||
result:=first_AndOrXor_assign;
|
||||
end;
|
||||
|
||||
in_neg_assign_x,
|
||||
in_not_assign_x:
|
||||
begin
|
||||
result:=first_NegNot_assign;
|
||||
end;
|
||||
|
||||
in_include_x_y,
|
||||
in_exclude_x_y:
|
||||
begin
|
||||
@ -4618,5 +4653,12 @@ implementation
|
||||
expectloc:=tcallparanode(tcallparanode(left).right).left.expectloc;
|
||||
end;
|
||||
|
||||
|
||||
function tinlinenode.first_NegNot_assign: tnode;
|
||||
begin
|
||||
result:=nil;
|
||||
expectloc:=left.expectloc;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -2059,7 +2059,8 @@ unit cgx86;
|
||||
begin
|
||||
tmpref:=ref;
|
||||
make_simple_ref(list,tmpref);
|
||||
check_register_size(size,reg);
|
||||
if not (op in [OP_NEG,OP_NOT]) then
|
||||
check_register_size(size,reg);
|
||||
if (op=OP_MUL) and not (cs_check_overflow in current_settings.localswitches) then
|
||||
op:=OP_IMUL;
|
||||
case op of
|
||||
|
@ -94,9 +94,11 @@ const
|
||||
fpc_in_delete_x_y_z = 83;
|
||||
fpc_in_reset_typedfile_name = 84;
|
||||
fpc_in_rewrite_typedfile_name = 85;
|
||||
fpc_in_and_assign_x_y = 86;
|
||||
fpc_in_or_assign_x_y = 87;
|
||||
fpc_in_xor_assign_x_y = 88;
|
||||
fpc_in_and_assign_x_y = 86;
|
||||
fpc_in_or_assign_x_y = 87;
|
||||
fpc_in_xor_assign_x_y = 88;
|
||||
fpc_in_neg_assign_x = 94;
|
||||
fpc_in_not_assign_x = 95;
|
||||
|
||||
{ Internal constant functions }
|
||||
fpc_in_const_sqr = 100;
|
||||
|
104
tests/test/cg/tnegnotassign1.pp
Normal file
104
tests/test/cg/tnegnotassign1.pp
Normal file
@ -0,0 +1,104 @@
|
||||
program tnegnotassign1;
|
||||
|
||||
uses unegnotassign;
|
||||
|
||||
{$R-,Q-}
|
||||
|
||||
procedure Check(Value, ExpectedValue: QWord);
|
||||
begin
|
||||
if Value <> ExpectedValue then
|
||||
begin
|
||||
Writeln('Error!');
|
||||
Halt(1);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
gr: record
|
||||
b: Byte;
|
||||
w: Word;
|
||||
d: DWord;
|
||||
q: QWord;
|
||||
end;
|
||||
|
||||
procedure Test_RegVar;
|
||||
var
|
||||
b: Byte;
|
||||
w: Word;
|
||||
d: DWord;
|
||||
q: QWord;
|
||||
begin
|
||||
b := $5A;
|
||||
NotAssignByte(b);
|
||||
Check(b,$A5);
|
||||
|
||||
w := $5A7E;
|
||||
NotAssignWord(w);
|
||||
Check(w, $A581);
|
||||
|
||||
d := $5A7EFF44;
|
||||
NotAssignDWord(d);
|
||||
Check(d, $A58100BB);
|
||||
|
||||
q := $5A7EFF4455AAFF00;
|
||||
NotAssignQWord(q);
|
||||
Check(q, $A58100BBAA5500FF);
|
||||
|
||||
b := $5A;
|
||||
NegAssignByte(b);
|
||||
Check(b,$A6);
|
||||
|
||||
w := $5A7E;
|
||||
NegAssignWord(w);
|
||||
Check(w, $A582);
|
||||
|
||||
d := $5A7EFF44;
|
||||
NegAssignDWord(d);
|
||||
Check(d, $A58100BC);
|
||||
|
||||
q := $5A7EFF4455AAFF00;
|
||||
NegAssignQWord(q);
|
||||
Check(q, $A58100BBAA550100);
|
||||
end;
|
||||
|
||||
procedure Test_Ref;
|
||||
begin
|
||||
gr.b := $5A;
|
||||
NotAssignByte(gr.b);
|
||||
Check(gr.b,$A5);
|
||||
|
||||
gr.w := $5A7E;
|
||||
NotAssignWord(gr.w);
|
||||
Check(gr.w, $A581);
|
||||
|
||||
gr.d := $5A7EFF44;
|
||||
NotAssignDWord(gr.d);
|
||||
Check(gr.d, $A58100BB);
|
||||
|
||||
gr.q := $5A7EFF4455AAFF00;
|
||||
NotAssignQWord(gr.q);
|
||||
Check(gr.q, $A58100BBAA5500FF);
|
||||
|
||||
gr.b := $5A;
|
||||
NegAssignByte(gr.b);
|
||||
Check(gr.b,$A6);
|
||||
|
||||
gr.w := $5A7E;
|
||||
NegAssignWord(gr.w);
|
||||
Check(gr.w, $A582);
|
||||
|
||||
gr.d := $5A7EFF44;
|
||||
NegAssignDWord(gr.d);
|
||||
Check(gr.d, $A58100BC);
|
||||
|
||||
gr.q := $5A7EFF4455AAFF00;
|
||||
NegAssignQWord(gr.q);
|
||||
Check(gr.q, $A58100BBAA550100);
|
||||
end;
|
||||
|
||||
begin
|
||||
Test_RegVar;
|
||||
Test_Ref;
|
||||
|
||||
Writeln('Ok!');
|
||||
end.
|
21
tests/test/cg/unegnotassign.pp
Normal file
21
tests/test/cg/unegnotassign.pp
Normal file
@ -0,0 +1,21 @@
|
||||
unit unegnotassign;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
fpc_in_neg_assign_x = 94;
|
||||
fpc_in_not_assign_x = 95;
|
||||
|
||||
procedure NegAssignByte(var X: Byte);[internproc:fpc_in_neg_assign_x];
|
||||
procedure NegAssignWord(var X: Word);[internproc:fpc_in_neg_assign_x];
|
||||
procedure NegAssignDWord(var X: DWord);[internproc:fpc_in_neg_assign_x];
|
||||
procedure NegAssignQWord(var X: QWord);[internproc:fpc_in_neg_assign_x];
|
||||
|
||||
procedure NotAssignByte(var X: Byte);[internproc:fpc_in_not_assign_x];
|
||||
procedure NotAssignWord(var X: Word);[internproc:fpc_in_not_assign_x];
|
||||
procedure NotAssignDWord(var X: DWord);[internproc:fpc_in_not_assign_x];
|
||||
procedure NotAssignQWord(var X: QWord);[internproc:fpc_in_not_assign_x];
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
Loading…
Reference in New Issue
Block a user