Explorar o código

* handle bitpacked booleans more efficiently

git-svn-id: trunk@38509 -
florian %!s(int64=7) %!d(string=hai) anos
pai
achega
a66016026b
Modificáronse 4 ficheiros con 122 adicións e 29 borrados
  1. 1 0
      .gitattributes
  2. 60 26
      compiler/avr/navrmat.pas
  3. 30 3
      compiler/ncgutil.pas
  4. 31 0
      tests/webtbs/tw33417.pp

+ 1 - 0
.gitattributes

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

+ 60 - 26
compiler/avr/navrmat.pas

@@ -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));
-
-                  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;
+            { 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;
+                  end;
+                 else
+                   internalerror(2003042401);
                end;
-              else
-                internalerror(2003042401);
-            end;
           end;
       end;
 

+ 30 - 3
compiler/ncgutil.pas

@@ -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 - 0
tests/webtbs/tw33417.pp

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