mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-14 10:20:21 +02:00
* handle bitpacked booleans more efficiently
git-svn-id: trunk@38509 -
This commit is contained in:
parent
fe8f7a9876
commit
a66016026b
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -16055,6 +16055,7 @@ tests/webtbs/tw3328a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3328b.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3334.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3340.pp svneol=native#text/plain
|
||||
tests/webtbs/tw33417.pp svneol=native#text/pascal
|
||||
tests/webtbs/tw3348.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3349.pp svneol=native#text/plain
|
||||
tests/webtbs/tw3351.pp svneol=native#text/plain
|
||||
|
@ -59,37 +59,71 @@ implementation
|
||||
var
|
||||
tmpreg,lreg : tregister;
|
||||
i : longint;
|
||||
falselabel,truelabel,skiplabel: TAsmLabel;
|
||||
begin
|
||||
if not handle_locjump then
|
||||
begin
|
||||
secondpass(left);
|
||||
case left.location.loc of
|
||||
LOC_FLAGS :
|
||||
begin
|
||||
location_copy(location,left.location);
|
||||
inverse_flags(location.resflags);
|
||||
end;
|
||||
LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,
|
||||
LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF :
|
||||
begin
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0));
|
||||
{ short code? }
|
||||
if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) and
|
||||
(left.location.sreg.bitlen=1) then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,left.location.sreg.subsetreg,left.location.sreg.startbit));
|
||||
current_asmdata.getjumplabel(truelabel);
|
||||
current_asmdata.getjumplabel(falselabel);
|
||||
{ sbrc does a jump without an explicit label,
|
||||
if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether }
|
||||
current_asmdata.getjumplabel(skiplabel);
|
||||
skiplabel.increfs;
|
||||
location_reset_jump(location,truelabel,falselabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel);
|
||||
end
|
||||
else if (left.location.loc in [LOC_SUBSETREF,LOC_CSUBSETREF]) and
|
||||
(left.location.sref.bitlen=1) and (left.location.sref.bitindexreg=NR_NO) then
|
||||
begin
|
||||
tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8);
|
||||
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,u8inttype,osuinttype,left.location.sref.ref,tmpreg);
|
||||
current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,tmpreg,left.location.sref.startbit));
|
||||
current_asmdata.getjumplabel(truelabel);
|
||||
current_asmdata.getjumplabel(falselabel);
|
||||
{ sbrc does a jump without an explicit label,
|
||||
if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether }
|
||||
current_asmdata.getjumplabel(skiplabel);
|
||||
skiplabel.increfs;
|
||||
location_reset_jump(location,truelabel,falselabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
|
||||
cg.a_label(current_asmdata.CurrAsmList,skiplabel);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel);
|
||||
end
|
||||
else
|
||||
case left.location.loc of
|
||||
LOC_FLAGS :
|
||||
begin
|
||||
location_copy(location,left.location);
|
||||
inverse_flags(location.resflags);
|
||||
end;
|
||||
LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF,
|
||||
LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE :
|
||||
begin
|
||||
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0));
|
||||
|
||||
tmpreg:=left.location.register;
|
||||
for i:=2 to tcgsize2size[left.location.size] do
|
||||
begin
|
||||
if i=5 then
|
||||
tmpreg:=left.location.registerhi
|
||||
else
|
||||
tmpreg:=cg.GetNextReg(tmpreg);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg));
|
||||
end;
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags:=F_EQ;
|
||||
tmpreg:=left.location.register;
|
||||
for i:=2 to tcgsize2size[left.location.size] do
|
||||
begin
|
||||
if i=5 then
|
||||
tmpreg:=left.location.registerhi
|
||||
else
|
||||
tmpreg:=cg.GetNextReg(tmpreg);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg));
|
||||
end;
|
||||
location_reset(location,LOC_FLAGS,OS_NO);
|
||||
location.resflags:=F_EQ;
|
||||
end;
|
||||
else
|
||||
internalerror(2003042401);
|
||||
end;
|
||||
else
|
||||
internalerror(2003042401);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -253,11 +253,38 @@ implementation
|
||||
begin
|
||||
opsize:=def_cgsize(p.resultdef);
|
||||
case p.location.loc of
|
||||
LOC_SUBSETREG,LOC_CSUBSETREG,
|
||||
LOC_SUBSETREG,LOC_CSUBSETREG:
|
||||
begin
|
||||
if p.location.sreg.bitlen=1 then
|
||||
begin
|
||||
tmpreg:=cg.getintregister(list,p.location.sreg.subsetregsize);
|
||||
hlcg.a_op_const_reg_reg(list,OP_AND,cgsize_orddef(p.location.sreg.subsetregsize),1 shl p.location.sreg.startbit,p.location.sreg.subsetreg,tmpreg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
tmpreg:=cg.getintregister(list,OS_INT);
|
||||
hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg);
|
||||
end;
|
||||
cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel);
|
||||
cg.a_jmp_always(list,falselabel);
|
||||
end;
|
||||
LOC_SUBSETREF,LOC_CSUBSETREF:
|
||||
begin
|
||||
tmpreg := cg.getintregister(list,OS_INT);
|
||||
hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg);
|
||||
if (p.location.sref.bitindexreg=NR_NO) and (p.location.sref.bitlen=1) then
|
||||
begin
|
||||
tmpreg:=cg.getintregister(list,OS_INT);
|
||||
hlcg.a_load_ref_reg(list,u8inttype,osuinttype,p.location.sref.ref,tmpreg);
|
||||
|
||||
if target_info.endian=endian_big then
|
||||
hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl (8-(p.location.sref.startbit+1)),tmpreg,tmpreg)
|
||||
else
|
||||
hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl p.location.sref.startbit,tmpreg,tmpreg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
tmpreg:=cg.getintregister(list,OS_INT);
|
||||
hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg);
|
||||
end;
|
||||
cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel);
|
||||
cg.a_jmp_always(list,falselabel);
|
||||
end;
|
||||
|
31
tests/webtbs/tw33417.pp
Normal file
31
tests/webtbs/tw33417.pp
Normal file
@ -0,0 +1,31 @@
|
||||
type
|
||||
tflags = bitpacked record // Flags
|
||||
bit0,bit1,bit2,bit3,bit4,bit5,bit6,bit7 : boolean;
|
||||
end;
|
||||
|
||||
var
|
||||
gflags : tflags;
|
||||
|
||||
procedure p;
|
||||
|
||||
var
|
||||
flags : tflags;
|
||||
begin
|
||||
flags:=gflags;
|
||||
if flags.bit5 then
|
||||
halt(1);
|
||||
if gflags.bit5 then
|
||||
halt(1);
|
||||
if not flags.bit6 then
|
||||
halt(1);
|
||||
if not gflags.bit6 then
|
||||
halt(1);
|
||||
end;
|
||||
|
||||
begin
|
||||
gflags.bit4:=false;
|
||||
gflags.bit5:=false;
|
||||
gflags.bit6:=true;
|
||||
p;
|
||||
writeln('ok');
|
||||
end.
|
Loading…
Reference in New Issue
Block a user