* factored out tcginnode.in_smallset

* indention changed to common compiler style

git-svn-id: trunk@22063 -
This commit is contained in:
florian 2012-08-11 22:07:36 +00:00
parent 9a82fb9eb4
commit c1bca748ee

View File

@ -41,12 +41,16 @@ interface
end; end;
Tsetparts=array[1..8] of Tsetpart; Tsetparts=array[1..8] of Tsetpart;
{ tcginnode }
tcginnode = class(tinnode) tcginnode = class(tinnode)
function pass_1: tnode;override; procedure in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint); virtual;
procedure pass_generate_code;override;
function pass_1: tnode;override;
procedure pass_generate_code;override;
protected protected
function checkgenjumps(out setparts: Tsetparts; out numparts: byte; out use_small: boolean): boolean; virtual; function checkgenjumps(out setparts: Tsetparts; out numparts: byte; out use_small: boolean): boolean; virtual;
function analizeset(const Aset:Tconstset;out setparts: Tsetparts; out numparts: byte;is_small:boolean):boolean;virtual; function analizeset(const Aset:Tconstset;out setparts: Tsetparts; out numparts: byte;is_small:boolean):boolean;virtual;
end; end;
tcgcasenode = class(tcasenode) tcgcasenode = class(tcasenode)
@ -96,25 +100,25 @@ implementation
*****************************************************************************} *****************************************************************************}
procedure tcgsetelementnode.pass_generate_code; procedure tcgsetelementnode.pass_generate_code;
begin begin
{ load first value in 32bit register } { load first value in 32bit register }
secondpass(left); secondpass(left);
if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,u32inttype,false); hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,u32inttype,false);
{ also a second value ? } { also a second value ? }
if assigned(right) then if assigned(right) then
begin begin
secondpass(right); secondpass(right);
if codegenerror then if codegenerror then
exit; exit;
if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,false); hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,false);
end; end;
{ we doesn't modify the left side, we check only the type } { we doesn't modify the left side, we check only the type }
location_copy(location,left.location); location_copy(location,left.location);
end; end;
{***************************************************************************** {*****************************************************************************
@ -178,6 +182,36 @@ implementation
end; end;
procedure tcginnode.in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint);
begin
{ location is always LOC_REGISTER }
location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
{ allocate a register for the result }
location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
{**************************** SMALL SET **********************}
if left.location.loc=LOC_CONSTANT then
begin
hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,
right.resultdef, resultdef,
left.location.value-setbase, right.location,
location.register);
end
else
begin
hlcg.location_force_reg(current_asmdata.CurrAsmList, left.location,
left.resultdef, opdef, true);
register_maybe_adjust_setbase(current_asmdata.CurrAsmList, left.location,
setbase);
hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList, left.resultdef,
right.resultdef, resultdef, left.location.register, right.location,
location.register);
end;
location.size := def_cgsize(resultdef);
location.register := cg.makeregsize(current_asmdata.CurrAsmList,
location.register, location.size);
end;
function tcginnode.checkgenjumps(out setparts: Tsetparts; out numparts: byte;out use_small: boolean): boolean; function tcginnode.checkgenjumps(out setparts: Tsetparts; out numparts: byte;out use_small: boolean): boolean;
begin begin
{ check if we can use smallset operation using btl which is limited { check if we can use smallset operation using btl which is limited
@ -231,7 +265,6 @@ implementation
genjumps := checkgenjumps(setparts,numparts,use_small); genjumps := checkgenjumps(setparts,numparts,use_small);
orgopsize := def_cgsize(left.resultdef); orgopsize := def_cgsize(left.resultdef);
orgopdef := left.resultdef; orgopdef := left.resultdef;
uopsize := OS_32; uopsize := OS_32;
@ -291,191 +324,177 @@ implementation
setbase:=tsetdef(right.resultdef).setbase; setbase:=tsetdef(right.resultdef).setbase;
if genjumps then if genjumps then
begin begin
{ location is always LOC_JUMP } { location is always LOC_JUMP }
location_reset(location,LOC_JUMP,OS_NO); location_reset(location,LOC_JUMP,OS_NO);
{ If register is used, use only lower 8 bits } { If register is used, use only lower 8 bits }
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false); hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false);
pleftreg := left.location.register; pleftreg := left.location.register;
{ how much have we already substracted from the x in the } { how much have we already substracted from the x in the }
{ "x in [y..z]" expression } { "x in [y..z]" expression }
adjustment := 0; adjustment := 0;
hr:=NR_NO; hr:=NR_NO;
for i:=1 to numparts do for i:=1 to numparts do
if setparts[i].range then if setparts[i].range then
{ use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) } { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
begin begin
{ is the range different from all legal values? } { is the range different from all legal values? }
if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then
begin begin
{ yes, is the lower bound <> 0? } { yes, is the lower bound <> 0? }
if (setparts[i].start <> 0) then if (setparts[i].start <> 0) then
{ we're going to substract from the left register, } { we're going to substract from the left register, }
{ so in case of a LOC_CREGISTER first move the value } { so in case of a LOC_CREGISTER first move the value }
{ to edi (not done before because now we can do the } { to edi (not done before because now we can do the }
{ move and substract in one instruction with LEA) } { move and substract in one instruction with LEA) }
if (left.location.loc = LOC_CREGISTER) and if (left.location.loc = LOC_CREGISTER) and
(hr<>pleftreg) then (hr<>pleftreg) then
begin begin
{ don't change this back to a_op_const_reg/a_load_reg_reg, since pleftreg must not be modified } { don't change this back to a_op_const_reg/a_load_reg_reg, since pleftreg must not be modified }
hr:=hlcg.getintregister(current_asmdata.CurrAsmList,opdef); hr:=hlcg.getintregister(current_asmdata.CurrAsmList,opdef);
hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,setparts[i].start,pleftreg,hr); hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,setparts[i].start,pleftreg,hr);
pleftreg:=hr; pleftreg:=hr;
end end
else else
begin begin
{ otherwise, the value is already in a register } { otherwise, the value is already in a register }
{ that can be modified } { that can be modified }
hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opdef, hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,
setparts[i].start-adjustment,pleftreg) setparts[i].start-adjustment,pleftreg)
end; end;
{ new total value substracted from x: } { new total value substracted from x: }
{ adjustment + (setparts[i].start - adjustment) } { adjustment + (setparts[i].start - adjustment) }
adjustment := setparts[i].start; adjustment := setparts[i].start;
{ check if result < b-a+1 (not "result <= b-a", since } { check if result < b-a+1 (not "result <= b-a", since }
{ we need a carry in case the element is in the range } { we need a carry in case the element is in the range }
{ (this will never overflow since we check at the } { (this will never overflow since we check at the }
{ beginning whether stop-start <> 255) } { beginning whether stop-start <> 255) }
hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, uopdef, OC_B, hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, uopdef, OC_B,
setparts[i].stop-setparts[i].start+1,pleftreg,current_procinfo.CurrTrueLabel); setparts[i].stop-setparts[i].start+1,pleftreg,current_procinfo.CurrTrueLabel);
end end
else else
{ if setparts[i].start = 0 and setparts[i].stop = 255, } { if setparts[i].start = 0 and setparts[i].stop = 255, }
{ it's always true since "in" is only allowed for bytes } { it's always true since "in" is only allowed for bytes }
begin begin
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel); hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
end; end;
end end
else else
begin begin
{ Emit code to check if left is an element } { Emit code to check if left is an element }
hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opdef, OC_EQ, hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opdef, OC_EQ,
setparts[i].stop-adjustment,pleftreg,current_procinfo.CurrTrueLabel); setparts[i].stop-adjustment,pleftreg,current_procinfo.CurrTrueLabel);
end; end;
{ To compensate for not doing a second pass } { To compensate for not doing a second pass }
right.location.reference.symbol:=nil; right.location.reference.symbol:=nil;
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel); hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
end end
else else
{*****************************************************************} {*****************************************************************}
{ NO JUMP TABLE GENERATION } { NO JUMP TABLE GENERATION }
{*****************************************************************} {*****************************************************************}
begin begin
{ location is always LOC_REGISTER } { We will now generated code to check the set itself, no jmps,
location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)}); handle smallsets separate, because it allows faster checks }
{ allocate a register for the result } if use_small then
location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize); begin
in_smallset(uopsize, opdef, setbase);
end
else
{************************** NOT SMALL SET ********************}
begin
{ location is always LOC_REGISTER }
location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
{ allocate a register for the result }
location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
{ We will now generated code to check the set itself, no jmps, if right.location.loc=LOC_CONSTANT then
handle smallsets separate, because it allows faster checks } begin
if use_small then { can it actually occur currently? CEC }
begin { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
{**************************** SMALL SET **********************}
if left.location.loc=LOC_CONSTANT then
begin
hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,right.resultdef,resultdef,
left.location.value-setbase,right.location,
location.register);
end
else
begin
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,
right.resultdef,resultdef,left.location.register,right.location,location.register);
end;
end
else
{************************** NOT SMALL SET ********************}
begin
if right.location.loc=LOC_CONSTANT then
begin
{ can it actually occur currently? CEC }
{ yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
{ note: this code assumes that left in [0..255], which is a valid } { note: this code assumes that left in [0..255], which is a valid }
{ assumption (other cases will be caught by range checking) (JM) } { assumption (other cases will be caught by range checking) (JM) }
{ load left in register } { load left in register }
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true); hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase); register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
{ emit bit test operation -- warning: do not use { emit bit test operation -- warning: do not use
location_force_reg() to force a set into a register, except location_force_reg() to force a set into a register, except
to a register of the same size as the set. The reason is to a register of the same size as the set. The reason is
that on big endian systems, this would require moving the that on big endian systems, this would require moving the
set to the most significant part of the new register, set to the most significant part of the new register,
and location_force_register can't do that (it does not and location_force_register can't do that (it does not
know the type). know the type).
a_bit_test_reg_loc_reg() properly takes into account the a_bit_test_reg_loc_reg() properly takes into account the
size of the set to adjust the register index to test } size of the set to adjust the register index to test }
hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList, hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,
left.resultdef,right.resultdef,resultdef, left.resultdef,right.resultdef,resultdef,
left.location.register,right.location,location.register); left.location.register,right.location,location.register);
{ now zero the result if left > nr_of_bits_in_right_register } { now zero the result if left > nr_of_bits_in_right_register }
hr := cg.getintregister(current_asmdata.CurrAsmList,location.size); hr := cg.getintregister(current_asmdata.CurrAsmList,location.size);
{ if left > tcgsize2size[opsize]*8 then hr := 0 else hr := $ffffffff } { if left > tcgsize2size[opsize]*8 then hr := 0 else hr := $ffffffff }
{ (left.location.size = location.size at this point) } { (left.location.size = location.size at this point) }
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, location.size, tcgsize2size[opsize]*8, left.location.register, hr); cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, location.size, tcgsize2size[opsize]*8, left.location.register, hr);
cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, location.size, (tcgsize2size[opsize]*8)-1, hr); cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, location.size, (tcgsize2size[opsize]*8)-1, hr);
{ if left > tcgsize2size[opsize]*8-1, then result := 0 else result := result of bit test } { if left > tcgsize2size[opsize]*8-1, then result := 0 else result := result of bit test }
cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, location.size, hr, location.register); cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, location.size, hr, location.register);
end { of right.location.loc=LOC_CONSTANT } end { of right.location.loc=LOC_CONSTANT }
{ do search in a normal set which could have >32 elements { do search in a normal set which could have >32 elements
but also used if the left side contains higher values > 32 } but also used if the left side contains higher values > 32 }
else if (left.location.loc=LOC_CONSTANT) then else if (left.location.loc=LOC_CONSTANT) then
begin begin
if (left.location.value < setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then if (left.location.value < setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then
{should be caught earlier } {should be caught earlier }
internalerror(2007020402); internalerror(2007020402);
hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.value-setbase, hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.value-setbase,
right.location,location.register); right.location,location.register);
end end
else else
begin begin
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true); hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase); register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
pleftreg := left.location.register; pleftreg := left.location.register;
if (opsize >= OS_S8) or { = if signed } if (opsize >= OS_S8) or { = if signed }
((left.resultdef.typ=orddef) and ((left.resultdef.typ=orddef) and
((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or ((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or
(torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or (torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or
((left.resultdef.typ=enumdef) and ((left.resultdef.typ=enumdef) and
((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or ((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or
(tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then (tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then
begin begin
current_asmdata.getjumplabel(l); current_asmdata.getjumplabel(l);
current_asmdata.getjumplabel(l2); current_asmdata.getjumplabel(l2);
needslabel := True; needslabel := True;
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, left.location.size, OC_BE, tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase, pleftreg, l); cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, left.location.size, OC_BE, tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase, pleftreg, l);
cg.a_load_const_reg(current_asmdata.CurrAsmList, location.size, 0, location.register); cg.a_load_const_reg(current_asmdata.CurrAsmList, location.size, 0, location.register);
cg.a_jmp_always(current_asmdata.CurrAsmList, l2); cg.a_jmp_always(current_asmdata.CurrAsmList, l2);
cg.a_label(current_asmdata.CurrAsmList, l); cg.a_label(current_asmdata.CurrAsmList, l);
end; end;
hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,right.resultdef,resultdef, hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,right.resultdef,resultdef,
pleftreg,right.location,location.register); pleftreg,right.location,location.register);
if needslabel then if needslabel then
cg.a_label(current_asmdata.CurrAsmList, l2); cg.a_label(current_asmdata.CurrAsmList, l2);
end; end;
end; location.size := def_cgsize(resultdef);
end; location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
location_freetemp(current_asmdata.CurrAsmList, right.location); end;
end;
location.size := def_cgsize(resultdef); location_freetemp(current_asmdata.CurrAsmList, right.location);
location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
end; end;
{***************************************************************************** {*****************************************************************************