소스 검색

* patch by Rika: improve ctuils.newalign/align, part of #39496

florian 3 년 전
부모
커밋
ab969e0a9b
1개의 변경된 파일29개의 추가작업 그리고 34개의 파일을 삭제
  1. 29 34
      compiler/cutils.pas

+ 29 - 34
compiler/cutils.pas

@@ -293,13 +293,13 @@ implementation
 
 
     function newalignment(oldalignment: longint; offset: int64): longint;
-      var
-        localoffset: longint;
       begin
-        localoffset:=longint(offset);
-        while (localoffset mod oldalignment)<>0 do
-          oldalignment:=oldalignment div 2;
-        newalignment:=oldalignment;
+        { oldalignment must be power of two.
+          Works even for negative offsets (but not alignments),
+          as two's complement of, say, 2^4+2^3 is 11000 and -2^4-2^3 is 11...1101000 -
+          both end with exactly N zeros, where N is the largest power of two that divides the number
+          (smallest power of two involved in these sums). }
+        result:=1 shl BsfQWord(qword(offset or oldalignment));
       end;
 
 
@@ -340,50 +340,45 @@ implementation
 
     function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
     {
-      return value <i> aligned <a> boundary
+      return value <i> aligned <a> boundary. <a> must be power of two.
     }
       begin
-        { for 0 and 1 no aligning is needed }
-        if a<=1 then
-          result:=i
-        else
-          begin
-            if i<0 then
-              result:=((i+1-a) div a) * a
-            else
-              result:=((i-1+a) div a) * a;
-          end;
+        { One-line formula for i >= 0 is
+          >>> (i + a - 1) and not (a - 1),
+          and for i < 0 is
+          >>> i and not (a - 1). }
+
+        if a>0 then
+          a:=a-1; { 'a' is decremented beforehand, this also allows a=0 as a synonym for a=1. }
+        if i>=0 then
+          i:=i+a;
+        result:=i and not a;
       end;
 
 
     function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
     {
-      return value <i> aligned <a> boundary
+      return value <i> aligned <a> boundary. <a> must be power of two.
     }
       begin
-        { for 0 and 1 no aligning is needed }
-        if a<=1 then
-          result:=i
-        else
-          begin
-            if i<0 then
-              result:=((i+1-a) div a) * a
-            else
-              result:=((i-1+a) div a) * a;
-          end;
+        { Copy of 'longint' version. }
+        if a>0 then
+          a:=a-1;
+        if i>=0 then
+          i:=i+a;
+        result:=i and not a;
       end;
 
 
     function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
     {
-      return value <i> aligned <a> boundary
+      return value <i> aligned <a> boundary. <a> must be power of two.
     }
       begin
-        { for 0 and 1 no aligning is needed }
-        if (a<=1) or (i=0) then
-          result:=i
-        else
-          result:=((i-1+a) div a) * a;
+        { No i < 0 case here. }
+        if a>0 then
+          a:=a-1;
+        result:=(i+a) and not a;
       end;