2
0
Эх сурвалжийг харах

* getregisterinline() can be used to replace multiple size variants
of the same register (or of a register and its aliases) -> make
sure that all relevant constraints are applied to it as well
(mantis #16980)

git-svn-id: trunk@15952 -

Jonas Maebe 15 жил өмнө
parent
commit
22b4860dd7

+ 1 - 0
.gitattributes

@@ -10629,6 +10629,7 @@ tests/webtbs/tw16949a.pp svneol=native#text/plain
 tests/webtbs/tw16949b.pp svneol=native#text/plain
 tests/webtbs/tw16954.pp svneol=native#text/plain
 tests/webtbs/tw1696.pp svneol=native#text/plain
+tests/webtbs/tw16980.pp svneol=native#text/plain
 tests/webtbs/tw1699.pp svneol=native#text/plain
 tests/webtbs/tw1709.pp svneol=native#text/plain
 tests/webtbs/tw17118.pp svneol=native#text/plain

+ 20 - 6
compiler/rgobj.pas

@@ -105,7 +105,11 @@ unit rgobj;
       Preginfo=^TReginfo;
 
       tspillreginfo = record
-        spillreg : tregister;
+        { a single register may appear more than once in an instruction,
+          but with different subregister types -> store all subregister types
+          that occur, so we can add the necessary constraints for the inline
+          register that will have to replace it }
+        spillregconstraints : set of TSubRegister;
         orgreg : tsuperregister;
         tempreg : tregister;
         regread,regwritten, mustbespilled: boolean;
@@ -164,7 +168,7 @@ unit rgobj;
         procedure add_cpu_interferences(p : tai);virtual;
         procedure add_constraints(reg:Tregister);virtual;
         function  get_alias(n:Tsuperregister):Tsuperregister;
-        function  getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
+        function  getregisterinline(list:TAsmList;const subregconstraints:Tsubregisterset):Tregister;
         procedure ungetregisterinline(list:TAsmList;r:Tregister);
         function  get_spill_subreg(r : tregister) : tsubregister;virtual;
         function  do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;virtual;
@@ -1451,15 +1455,24 @@ unit rgobj;
     end;
 
 
-    function trgobj.getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
+    function trgobj.getregisterinline(list:TAsmList;const subregconstraints:Tsubregisterset):Tregister;
       var
         p : Tsuperregister;
+        subreg: tsubregister;
       begin
+        for subreg:=high(tsubregister) downto low(tsubregister) do
+          if subreg in subregconstraints then
+            break;
         p:=getnewreg(subreg);
         live_registers.add(p);
         result:=newreg(regtype,p,subreg);
         add_edges_used(p);
         add_constraints(result);
+        { also add constraints for other sizes used for this register }
+        if subreg<>low(tsubregister) then
+          for subreg:=pred(subreg) downto low(tsubregister) do
+            if subreg in subregconstraints then
+              add_constraints(newreg(regtype,getsupreg(result),subreg));
       end;
 
 
@@ -1872,7 +1885,7 @@ unit rgobj;
           if tmpindex > high(regs) then
             internalerror(2003120301);
           regs[tmpindex].orgreg := supreg;
-          regs[tmpindex].spillreg:=reg;
+          include(regs[tmpindex].spillregconstraints,get_spill_subreg(reg));
           if supregset_in(r,supreg) then
             begin
               { add/update info on this register }
@@ -1910,6 +1923,7 @@ unit rgobj;
               end;
         end;
 
+
       var
         loadpos,
         storepos : tai;
@@ -2036,7 +2050,7 @@ unit rgobj;
             begin
               if mustbespilled and regread then
                 begin
-                  tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
+                  tempreg:=getregisterinline(list,regs[counter].spillregconstraints);
                   do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],tempreg);
                 end;
             end;
@@ -2063,7 +2077,7 @@ unit rgobj;
                 begin
                   { When the register is also loaded there is already a register assigned }
                   if (not regread) then
-                    tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
+                    tempreg:=getregisterinline(list,regs[counter].spillregconstraints);
                   { The original instruction will be the next that uses this register, this
                     also needs to be done for read-write registers }
                   add_reg_instruction(instr,tempreg,1);

+ 34 - 0
tests/webtbs/tw16980.pp

@@ -0,0 +1,34 @@
+{ %norun }
+
+{$mode delphi}
+{$packset 4}
+type
+  TColorComponent = (ccRed, ccGreen, ccBlue, ccAlpha);
+  TColorMask = set of TColorComponent;
+
+  TGLStateCache = class
+  private
+    FColorWriteMask: array[0..15] of TColorMask;
+    procedure SetColorWriteMask(Index: Integer; const Value: TColorMask);
+  end;
+  TGLuint = cardinal;
+  tglboolean = boolean;
+
+var
+  glColorMaski: procedure(index: TGLuint; r: TGLboolean; g: TGLboolean;
+                            b: TGLboolean; a: TGLboolean);{$IFDEF MSWINDOWS} stdcall; {$ENDIF} {$IFDEF UNIX} cdecl; {$ENDIF}
+
+procedure TGLStateCache.SetColorWriteMask(Index: Integer;
+  const Value: TColorMask);
+begin
+//  if FColorWriteMask[Index]<>Value then
+  begin
+    FColorWriteMask[Index] := Value;
+    glColorMaski(Index, ccRed in Value, ccGreen in Value, ccBlue in Value,
+                 ccAlpha in Value);
+  end;
+end;
+
+
+begin
+end.