+ 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:
nickysn 2017-04-07 16:02:40 +00:00
parent 8024fcd7ec
commit 256dc546ac
11 changed files with 290 additions and 36 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
*****************************************************************************}

View File

@ -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.

View File

@ -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

View File

@ -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;

View 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.

View 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.