これは、(ほとんどの場合)Visual Studioで表示される値とコードを生成するアルゴリズムのドキュメントへのリンクであり、可変整数を定数整数で除算するためにGCCで引き続き使用されていると想定しています。
http://gmplib.org/~tege/divcnst-pldi94.pdf
この記事では、uwordはNビット、udwordは2Nビット、n =分子=被除数、d =分母=除数、ℓは最初にceil(log2(d))に設定され、shpreはプレシフトです(乗算の前に使用) )= e = dの後続ゼロビットの数、shpostはポストシフト(乗算後に使用)、precは精度= N-e = N-shpreです。目標は、シフト前、シフト後、シフト後のn / dの計算を最適化することです。
udword乗数(最大サイズはN + 1ビット)の生成方法を定義している図6.2まで下にスクロールしますが、プロセスを明確に説明していません。これについては以下で説明します。
図4.2と図6.2は、ほとんどの除数について、乗数をNビット以下の乗数に削減する方法を示しています。式4.5は、図4.1および4.2のN + 1ビット乗算器を処理するために使用される式がどのように導出されたかを説明しています。
最新のX86およびその他のプロセッサの場合、乗算時間は固定されているため、プリシフトはこれらのプロセッサでは効果がありませんが、乗算器をN + 1ビットからNビットに減らすのに役立ちます。GCCまたはVisual StudioがX86ターゲットのシフト前を排除したかどうかはわかりません。
図6.2に戻ります。mlowとmhighの分子(被除数)は、分母(除数)> 2 ^(N-1)(when == N => mlow = 2 ^(2N)の場合)の場合にのみ、udwordより大きくできます。 n / dの最適化された置換は比較(n> = dの場合、q = 1、それ以外の場合はq = 0)であるため、乗数は生成されません。mlowとmhighの初期値はN + 1ビットであり、2つのudword / uword除算を使用して各N + 1ビット値(mlowまたはmhigh)を生成できます。例として64ビットモードでX86を使用する場合:
; upper 8 bytes of dividend = 2^(ℓ) = (upper part of 2^(N+ℓ))
; lower 8 bytes of dividend for mlow = 0
; lower 8 bytes of dividend for mhigh = 2^(N+ℓ-prec) = 2^(ℓ+shpre) = 2^(ℓ+e)
dividend dq 2 dup(?) ;16 byte dividend
divisor dq 1 dup(?) ; 8 byte divisor
; ...
mov rcx,divisor
mov rdx,0
mov rax,dividend+8 ;upper 8 bytes of dividend
div rcx ;after div, rax == 1
mov rax,dividend ;lower 8 bytes of dividend
div rcx
mov rdx,1 ;rdx:rax = N+1 bit value = 65 bit value
これはGCCでテストできます。j = i / 5がどのように処理されるかについてはすでに説明しました。j = i / 7がどのように処理されるかを見てください(N + 1ビットの乗算器の場合)。
現在のほとんどのプロセッサでは、乗算のタイミングが固定されているため、プリシフトは必要ありません。X86の場合、最終結果は、ほとんどの除数の2つの命令シーケンスと、7などの除数の5つの命令シーケンスです(pdfファイルの式4.5と図4.2に示すようにN + 1ビットの乗数をエミュレートするため)。X86-64コードの例:
; rax = dividend, rbx = 64 bit (or less) multiplier, rcx = post shift count
; two instruction sequence for most divisors:
mul rbx ;rdx = upper 64 bits of product
shr rdx,cl ;rdx = quotient
;
; five instruction sequence for divisors like 7
; to emulate 65 bit multiplier (rbx = lower 64 bits of multiplier)
mul rbx ;rdx = upper 64 bits of product
sub rbx,rdx ;rbx -= rdx
shr rbx,1 ;rbx >>= 1
add rdx,rbx ;rdx = upper 64 bits of corrected product
shr rdx,cl ;rdx = quotient
; ...