diff --git a/compiler/cutils.pas b/compiler/cutils.pas index 1b92d8f51d..170bad2451 100644 --- a/compiler/cutils.pas +++ b/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 aligned boundary + return value aligned boundary. 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 aligned boundary + return value aligned boundary. 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 aligned boundary + return value aligned boundary. 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;