[インデックス 14915] ファイルの概要
このコミットは、Go言語のビルドシステムにおいて、386アーキテクチャ向けのコンパイル時に使用されるCPU機能の検出および指定方法を改善するものです。具体的には、GO386環境変数のデフォルト値および内部的なCPU機能検出ロジックを、より正確なsseからsse2へと変更しています。これにより、GoコンパイラがSSE2命令セットの利用可能性をより正確に判断し、それに基づいて最適化されたコードを生成できるようになります。
コミット
commit d795f07718f0011b035adad4a8fb5f5a33cb7ba1
Author: Russ Cox <rsc@golang.org>
Date: Fri Jan 18 15:10:36 2013 -0500
build: change GO386=sse to GO386=sse2
sse2 is a more precise description of the requirement,
and it matches what people will see in, for example
grep sse2 /proc/cpuinfo # linux
sysctl hw.optional.sse2 # os x
R=golang-dev, dsymonds, iant
CC=golang-dev
https://golang.org/cl/7057050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d795f07718f0011b035adad4a8fb5f5a33cb7ba1
元コミット内容
このコミットの目的は、GoのビルドプロセスにおけるGO386環境変数の扱いを変更することです。以前はGO386=sseとしていたものをGO386=sse2に変更しています。コミットメッセージによると、sse2の方が要件をより正確に記述しており、Linuxの/proc/cpuinfoやmacOSのsysctl hw.optional.sse2といった一般的なシステムツールでユーザーが確認する情報と一致するため、この変更が行われました。これは、Goコンパイラが生成するコードの最適化レベルを、ターゲットCPUの実際の機能に合わせて調整するためのものです。
変更の背景
この変更の背景には、Go言語がサポートするx86アーキテクチャ(特に32ビット版の386)におけるCPUの命令セット拡張の進化があります。
- SSE (Streaming SIMD Extensions): IntelがPentium IIIプロセッサで導入したSIMD(Single Instruction, Multiple Data)命令セットです。浮動小数点演算やマルチメディア処理の高速化を目的としています。
- SSE2 (Streaming SIMD Extensions 2): IntelがPentium 4プロセッサで導入したSSEの拡張版です。SSE2は、SSEの浮動小数点演算機能に加えて、整数演算や倍精度浮動小数点演算にもSIMD機能を提供します。現代のほとんどのx86-64プロセッサはSSE2をサポートしており、32ビットモードでも利用可能です。
Goのビルドシステムは、ターゲットとなるCPUが特定の命令セットをサポートしているかどうかを検出し、それに応じてコンパイル時の最適化を適用します。以前はsseという一般的な用語を使用していましたが、これはSSEとSSE2のどちらを指すのか曖昧でした。多くの現代のCPUはSSE2をサポートしており、GoコンパイラがSSE2命令を利用できる場合、より効率的なコードを生成できます。
このコミットは、以下の理由からsseからsse2への変更を行いました。
- 精度の向上:
sse2は、Goコンパイラが期待するCPUの命令セット要件をより正確に表現しています。これにより、コンパイラはより適切な最適化を適用できます。 - ユーザーとの整合性: Linuxの
/proc/cpuinfoやmacOSのsysctl hw.optional.sse2といった一般的なシステムツールでユーザーがCPUの機能を確認する際に、sse2という用語が広く使われています。この変更により、Goのビルド設定とシステム情報との間に一貫性が生まれ、ユーザーが自身の環境でGoをビルドする際の混乱が減少します。 - デフォルトの最適化:
GO386が設定されていない場合、GoのビルドシステムはCPUの機能を自動検出します。この自動検出ロジックがcansse()からcansse2()に変わることで、より新しい命令セットであるSSE2がデフォルトで考慮されるようになり、結果としてより高性能なバイナリが生成される可能性が高まります。
前提知識の解説
このコミットを理解するためには、以下の概念を把握しておく必要があります。
1. Go言語のビルドシステムとクロスコンパイル
Go言語は、強力なクロスコンパイル機能を内蔵しています。これは、あるオペレーティングシステム(OS)やアーキテクチャ上で、別のOSやアーキテクチャ向けのバイナリを生成できる能力です。この機能は、GOOS、GOARCH、GOARM、GO386などの環境変数によって制御されます。
GOOS: ターゲットとなるOS(例:linux,windows,darwin)。GOARCH: ターゲットとなるCPUアーキテクチャ(例:amd64,386,arm,arm64)。GO386:GOARCH=386の場合にのみ関連する環境変数で、32ビットx86アーキテクチャ向けの特定のCPU機能(命令セット拡張)を指定します。この変数は、コンパイラが生成するコードの最適化レベルに影響を与えます。
Goのビルドプロセスは、これらの環境変数を参照して、適切なコンパイラツールチェーンを選択し、ターゲット環境に合わせたバイナリを生成します。
2. x86アーキテクチャと命令セット拡張 (SSE, SSE2)
x86アーキテクチャは、IntelとAMDによって開発された命令セットアーキテクチャです。長年にわたり、性能向上と新機能の追加のために様々な命令セット拡張が導入されてきました。
-
SIMD (Single Instruction, Multiple Data): 一つの命令で複数のデータ要素に対して同じ操作を実行する並列処理の形式です。これにより、特にマルチメディア処理、科学技術計算、グラフィックス処理などで大幅な性能向上が期待できます。
-
SSE (Streaming SIMD Extensions):
- IntelがPentium IIIプロセッサで導入。
- 8つの128ビットXMMレジスタ(
XMM0~XMM7)と、新しいデータ型(単精度浮動小数点数)を導入。 - 主に単精度浮動小数点演算のSIMD処理を目的としています。
-
SSE2 (Streaming SIMD Extensions 2):
- IntelがPentium 4プロセッサで導入。
- SSEの機能を拡張し、倍精度浮動小数点数と整数データ型に対するSIMD演算をサポート。
- 現代のほとんどのx86-64プロセッサはSSE2をサポートしており、32ビットモードでも利用可能です。Windows XP SP2以降の32ビット版Windowsは、SSE2を必須要件としています。
Goコンパイラは、これらの命令セット拡張を利用して、より効率的なコード(例えば、浮動小数点演算やメモリ操作を高速化するコード)を生成できます。
3. CPUID命令
CPUID命令は、x86アーキテクチャのプロセッサが提供する命令で、プロセッサの機能や情報をプログラムから問い合わせるために使用されます。オペレーティングシステムやアプリケーションは、この命令を使ってプロセッサがサポートする命令セット拡張(SSE, SSE2, AVXなど)やキャッシュ構成などの情報を取得し、それに基づいて最適なコードパスを選択したり、特定の機能を有効にしたりします。
Goのビルドシステムでは、cansse()やcansse2()のような関数が内部的にCPUID命令を利用して、実行環境のCPUが特定の命令セットをサポートしているかを判断します。
技術的詳細
このコミットは、Goのビルドシステムにおける386アーキテクチャ向けのCPU機能検出ロジックと、それに関連するコンパイルオプションの扱いを変更しています。
1. GO386環境変数のデフォルト値の変更
src/cmd/dist/build.cのinit()関数は、GO386環境変数が設定されていない場合にデフォルト値を決定するロジックを含んでいます。
変更前:
if(cansse())
bwritestr(&b, "sse");
else
bwritestr(&b, "387");
変更後:
if(cansse2())
bwritestr(&b, "sse2");
else
bwritestr(&b, "387");
この変更により、GO386が明示的に設定されていない場合、ビルドシステムはまずcansse2()を呼び出してSSE2のサポートをチェックします。SSE2が利用可能であればGO386はsse2に設定され、そうでなければ従来の387(x87 FPU命令セットのみを使用)に設定されます。これにより、現代のCPUではデフォルトでSSE2が利用されるようになり、より高性能なバイナリが生成される可能性が高まります。
2. cansse()からcansse2()への関数名の変更とロジックの統一
複数のファイル(src/cmd/dist/a.h, src/cmd/dist/plan9.c, src/cmd/dist/unix.c, src/cmd/dist/windows.c)で、cansse()という関数名がcansse2()に変更されています。これは単なるリネームではなく、その関数が実際にSSE2のサポートをチェックするようになったことを明確にするためのものです。
これらのファイルは、Goのビルドツールであるdistコマンドの一部であり、異なるOS(Plan 9, Unix系, Windows)上でのCPU機能検出ロジックをカプセル化しています。cansse2()関数は、内部的にCPUID命令を使用して、プロセッサがSSE2命令セットをサポートしているかどうかを判断します。
例えば、src/cmd/dist/unix.cやsrc/cmd/dist/windows.cでは、__cpuidまたはcpuid関数を呼び出してCPU情報を取得し、特定のビット(SSE2のサポートを示すビット)がセットされているかを確認します。
3. src/cmd/gc/lex.cにおけるGO386のパースロジックの変更
src/cmd/gc/lex.cはGoコンパイラの字句解析器の一部であり、ビルド時に設定されるGO386の値に基づいて、コンパイラがSSE命令を使用するかどうかを決定します。
変更前:
use_sse = strcmp(getgo386(), "sse") == 0;
変更後:
if(thechar == '8') { // '8' corresponds to GOARCH=386
p = getgo386();
if(strcmp(p, "387") == 0)
use_sse = 0;
else if(strcmp(p, "sse2") == 0)
use_sse = 1;
else
sysfatal("unsupported setting GO386=%s", p);
}
この変更により、コンパイラはGO386の値として"sse"ではなく"sse2"を期待するようになります。
GO386="387"の場合、use_sseは0となり、SSE/SSE2命令は使用されません。GO386="sse2"の場合、use_sseは1となり、コンパイラはSSE2命令を利用した最適化を行います。- これら以外の値が設定された場合は、致命的なエラー(
sysfatal)が発生し、サポートされていない設定であることをユーザーに通知します。
この変更は、コンパイラがGO386の値に基づいて、生成するアセンブリコードにSSE2命令を含めるかどうかを制御するための重要な部分です。
影響
この変更は、主に32ビットx86(GOARCH=386)向けのGoバイナリのビルドに影響を与えます。
- 性能向上: 現代のCPUでビルドする場合、デフォルトでSSE2が有効になるため、浮動小数点演算や一部のメモリ操作が高速化され、Goアプリケーションの実行性能が向上する可能性があります。
- 互換性: 非常に古いCPU(SSE2をサポートしないPentium III以前のプロセッサなど)でGoバイナリを実行しようとすると、
GO386=sse2でビルドされたバイナリは実行できない可能性があります。しかし、そのような環境は現在では非常に稀であり、Goのターゲット環境としては通常考慮されません。 - ビルドの明確化:
GO386=sse2というより正確な記述により、ビルド設定が何を意味するのかが明確になります。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルとコードの変更点は以下の通りです。
-
src/cmd/dist/a.h:bool cansse(void);がbool cansse2(void);に変更。distコマンドのヘッダーファイルで、CPU機能検出関数の宣言が更新されました。
-
src/cmd/dist/build.c:init()関数内で、GO386が未設定の場合のデフォルト値決定ロジックが変更。if(cansse())がif(cansse2())に変更。bwritestr(&b, "sse");がbwritestr(&b, "sse2");に変更。- これにより、デフォルトでSSE2のサポートがチェックされ、
GO386にsse2が設定されるようになりました。
-
src/cmd/dist/plan9.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Plan 9向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/dist/unix.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Unix系OS向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/dist/windows.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Windows向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/gc/lex.c:main()関数内で、GO386の値に基づいてuse_sseフラグを設定するロジックが変更。use_sse = strcmp(getgo386(), "sse") == 0;が削除。GOARCH=386の場合(thechar == '8')、getgo386()で取得した値が"387"ならuse_sse = 0、"sse2"ならuse_sse = 1に設定されるようになりました。- サポートされていない
GO386の値が検出された場合にsysfatalでエラーを出すロジックが追加されました。
コアとなるコードの解説
src/cmd/dist/a.h
このファイルは、Goのビルドツールであるdistコマンドが使用する共通のヘッダーファイルです。cansse()からcansse2()への変更は、このヘッダーで宣言されているCPU機能検出関数の名前が、より正確なSSE2のチェックを反映するように更新されたことを示しています。
src/cmd/dist/build.c
このファイルは、Goのビルドプロセスを制御するdistコマンドの主要な部分です。init()関数は、ビルド環境の初期化を担当し、その中でGO386環境変数のデフォルト値を設定します。
変更されたコードブロックは、GO386がユーザーによって明示的に設定されていない場合に実行されます。
if(b.len == 0) { // GO386が設定されていない場合
if(cansse2()) // SSE2が利用可能かチェック
bwritestr(&b, "sse2"); // 利用可能なら "sse2" を設定
else
bwritestr(&b, "387"); // 利用不可なら "387" を設定
}
このロジックにより、現代のCPUでは自動的にGO386=sse2が選択され、コンパイラがSSE2命令を利用した最適化を行うようになります。
src/cmd/dist/plan9.c, src/cmd/dist/unix.c, src/cmd/dist/windows.c
これらのファイルは、それぞれPlan 9、Unix系OS、Windowsといった異なるプラットフォームにおけるCPU機能検出の実装を含んでいます。cansse()関数がcansse2()にリネームされたのは、これらの関数が実際にSSE2のサポートをチェックするようになったことを明確にするためです。
例えば、src/cmd/dist/unix.cやsrc/cmd/dist/windows.cでは、CPUID命令(__cpuidまたはcpuid関数を通じて)を使用してCPUの機能フラグを読み取り、SSE2のサポートを示すビット(通常はEDXレジスタのビット26)がセットされているかを確認します。
src/cmd/gc/lex.c
このファイルはGoコンパイラの字句解析器の一部であり、コンパイル時にGO386の値に基づいてuse_sseという内部フラグを設定します。このフラグは、コンパイラのバックエンドがSSE/SSE2命令を生成するかどうかを制御します。
変更されたコードブロックは、GOARCHが386(thechar == '8')の場合に実行されます。
if(thechar == '8') { // GOARCH=386の場合
p = getgo386(); // GO386の値を取得
if(strcmp(p, "387") == 0) // "387" ならSSEを使わない
use_sse = 0;
else if(strcmp(p, "sse2") == 0) // "sse2" ならSSEを使う
use_sse = 1;
else
sysfatal("unsupported setting GO386=%s", p); // それ以外はエラー
}
このロジックにより、コンパイラはGO386の値が"sse2"である場合にのみSSE2命令を生成するようになり、"sse"という古い値はサポートされなくなりました。これにより、コンパイラの動作とビルドシステムの意図がより密接に連携するようになります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Goの環境変数に関するドキュメント: https://go.dev/doc/install/source#environment (このコミット時点では古い情報である可能性がありますが、概念は共通です)
- GoのIssueトラッカー (このコミットに関連する議論があるかもしれません): https://github.com/golang/go/issues
参考にした情報源リンク
- Streaming SIMD Extensions (SSE) - Wikipedia: https://ja.wikipedia.org/wiki/Streaming_SIMD_Extensions
- Streaming SIMD Extensions 2 (SSE2) - Wikipedia: https://ja.wikipedia.org/wiki/Streaming_SIMD_Extensions_2
- CPUID - Wikipedia: https://ja.wikipedia.org/wiki/CPUID
- Goのビルドシステムに関する一般的な情報 (Goのソースコードや関連するブログ記事、フォーラムの議論など)
grep sse2 /proc/cpuinfoおよびsysctl hw.optional.sse2のコマンド出力例に関する情報 (一般的なLinux/macOSのドキュメントやフォーラム)```markdown
[インデックス 14915] ファイルの概要
このコミットは、Go言語のビルドシステムにおいて、386アーキテクチャ向けのコンパイル時に使用されるCPU機能の検出および指定方法を改善するものです。具体的には、GO386環境変数のデフォルト値および内部的なCPU機能検出ロジックを、より正確なsseからsse2へと変更しています。これにより、GoコンパイラがSSE2命令セットの利用可能性をより正確に判断し、それに基づいて最適化されたコードを生成できるようになります。
コミット
commit d795f07718f0011b035adad4a8fb5f5a33cb7ba1
Author: Russ Cox <rsc@golang.org>
Date: Fri Jan 18 15:10:36 2013 -0500
build: change GO386=sse to GO386=sse2
sse2 is a more precise description of the requirement,
and it matches what people will see in, for example
grep sse2 /proc/cpuinfo # linux
sysctl hw.optional.sse2 # os x
R=golang-dev, dsymonds, iant
CC=golang-dev
https://golang.org/cl/7057050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d795f07718f0011b035adad4a8fb5f5a33cb7ba1
元コミット内容
このコミットの目的は、GoのビルドプロセスにおけるGO386環境変数の扱いを変更することです。以前はGO386=sseとしていたものをGO386=sse2に変更しています。コミットメッセージによると、sse2の方が要件をより正確に記述しており、Linuxの/proc/cpuinfoやmacOSのsysctl hw.optional.sse2といった一般的なシステムツールでユーザーが確認する情報と一致するため、この変更が行われました。これは、Goコンパイラが生成するコードの最適化レベルを、ターゲットCPUの実際の機能に合わせて調整するためのものです。
変更の背景
この変更の背景には、Go言語がサポートするx86アーキテクチャ(特に32ビット版の386)におけるCPUの命令セット拡張の進化があります。
- SSE (Streaming SIMD Extensions): IntelがPentium IIIプロセッサで導入したSIMD(Single Instruction, Multiple Data)命令セットです。浮動小数点演算やマルチメディア処理の高速化を目的としています。
- SSE2 (Streaming SIMD Extensions 2): IntelがPentium 4プロセッサで導入したSSEの拡張版です。SSE2は、SSEの浮動小数点演算機能に加えて、整数演算や倍精度浮動小数点演算にもSIMD機能を提供します。現代のほとんどのx86-64プロセッサはSSE2をサポートしており、32ビットモードでも利用可能です。
Goのビルドシステムは、ターゲットとなるCPUが特定の命令セットをサポートしているかどうかを検出し、それに応じてコンパイル時の最適化を適用します。以前はsseという一般的な用語を使用していましたが、これはSSEとSSE2のどちらを指すのか曖昧でした。多くの現代のCPUはSSE2をサポートしており、GoコンパイラがSSE2命令を利用できる場合、より効率的なコードを生成できます。
このコミットは、以下の理由からsseからsse2への変更を行いました。
- 精度の向上:
sse2は、Goコンパイラが期待するCPUの命令セット要件をより正確に表現しています。これにより、コンパイラはより適切な最適化を適用できます。 - ユーザーとの整合性: Linuxの
/proc/cpuinfoやmacOSのsysctl hw.optional.sse2といった一般的なシステムツールでユーザーがCPUの機能を確認する際に、sse2という用語が広く使われています。この変更により、Goのビルド設定とシステム情報との間に一貫性が生まれ、ユーザーが自身の環境でGoをビルドする際の混乱が減少します。 - デフォルトの最適化:
GO386が設定されていない場合、GoのビルドシステムはCPUの機能を自動検出します。この自動検出ロジックがcansse()からcansse2()に変わることで、より新しい命令セットであるSSE2がデフォルトで考慮されるようになり、結果としてより高性能なバイナリが生成される可能性が高まります。
前提知識の解説
このコミットを理解するためには、以下の概念を把握しておく必要があります。
1. Go言語のビルドシステムとクロスコンパイル
Go言語は、強力なクロスコンパイル機能を内蔵しています。これは、あるオペレーティングシステム(OS)やアーキテクチャ上で、別のOSやアーキテクチャ向けのバイナリを生成できる能力です。この機能は、GOOS、GOARCH、GOARM、GO386などの環境変数によって制御されます。
GOOS: ターゲットとなるOS(例:linux,windows,darwin)。GOARCH: ターゲットとなるCPUアーキテクチャ(例:amd64,386,arm,arm64)。GO386:GOARCH=386の場合にのみ関連する環境変数で、32ビットx86アーキテクチャ向けの特定のCPU機能(命令セット拡張)を指定します。この変数は、コンパイラが生成するコードの最適化レベルに影響を与えます。
Goのビルドプロセスは、これらの環境変数を参照して、適切なコンパイラツールチェーンを選択し、ターゲット環境に合わせたバイナリを生成します。
2. x86アーキテクチャと命令セット拡張 (SSE, SSE2)
x86アーキテクチャは、IntelとAMDによって開発された命令セットアーキテクチャです。長年にわたり、性能向上と新機能の追加のために様々な命令セット拡張が導入されてきました。
-
SIMD (Single Instruction, Multiple Data): 一つの命令で複数のデータ要素に対して同じ操作を実行する並列処理の形式です。これにより、特にマルチメディア処理、科学技術計算、グラフィックス処理などで大幅な性能向上が期待できます。
-
SSE (Streaming SIMD Extensions):
- IntelがPentium IIIプロセッサで導入。
- 8つの128ビットXMMレジスタ(
XMM0~XMM7)と、新しいデータ型(単精度浮動小数点数)を導入。 - 主に単精度浮動小数点演算のSIMD処理を目的としています。
-
SSE2 (Streaming SIMD Extensions 2):
- IntelがPentium 4プロセッサで導入。
- SSEの機能を拡張し、倍精度浮動小数点数と整数データ型に対するSIMD演算をサポート。
- 現代のほとんどのx86-64プロセッサはSSE2をサポートしており、32ビットモードでも利用可能です。Windows XP SP2以降の32ビット版Windowsは、SSE2を必須要件としています。
Goコンパイラは、これらの命令セット拡張を利用して、より効率的なコード(例えば、浮動小数点演算やメモリ操作を高速化するコード)を生成できます。
3. CPUID命令
CPUID命令は、x86アーキテクチャのプロセッサが提供する命令で、プロセッサの機能や情報をプログラムから問い合わせるために使用されます。オペレーティングシステムやアプリケーションは、この命令を使ってプロセッサがサポートする命令セット拡張(SSE, SSE2, AVXなど)やキャッシュ構成などの情報を取得し、それに基づいて最適なコードパスを選択したり、特定の機能を有効にしたりします。
Goのビルドシステムでは、cansse()やcansse2()のような関数が内部的にCPUID命令を利用して、実行環境のCPUが特定の命令セットをサポートしているかを判断します。
技術的詳細
このコミットは、Goのビルドシステムにおける386アーキテクチャ向けのCPU機能検出ロジックと、それに関連するコンパイルオプションの扱いを変更しています。
1. GO386環境変数のデフォルト値の変更
src/cmd/dist/build.cのinit()関数は、GO386環境変数が設定されていない場合にデフォルト値を決定するロジックを含んでいます。
変更前:
if(cansse())
bwritestr(&b, "sse");
else
bwritestr(&b, "387");
変更後:
if(cansse2())
bwritestr(&b, "sse2");
else
bwritestr(&b, "387");
この変更により、GO386が明示的に設定されていない場合、ビルドシステムはまずcansse2()を呼び出してSSE2のサポートをチェックします。SSE2が利用可能であればGO386はsse2に設定され、そうでなければ従来の387(x87 FPU命令セットのみを使用)に設定されます。これにより、現代のCPUではデフォルトでSSE2が利用されるようになり、より高性能なバイナリが生成される可能性が高まります。
2. cansse()からcansse2()への関数名の変更とロジックの統一
複数のファイル(src/cmd/dist/a.h, src/cmd/dist/plan9.c, src/cmd/dist/unix.c, src/cmd/dist/windows.c)で、cansse()という関数名がcansse2()に変更されています。これは単なるリネームではなく、その関数が実際にSSE2のサポートをチェックするようになったことを明確にするためのものです。
これらのファイルは、Goのビルドツールであるdistコマンドの一部であり、異なるOS(Plan 9, Unix系, Windows)上でのCPU機能検出ロジックをカプセル化しています。cansse2()関数は、内部的にCPUID命令を使用して、プロセッサがSSE2命令セットをサポートしているかどうかを判断します。
例えば、src/cmd/dist/unix.cやsrc/cmd/dist/windows.cでは、__cpuidまたはcpuid関数を呼び出してCPU情報を取得し、特定のビット(SSE2のサポートを示すビット)がセットされているかを確認します。
3. src/cmd/gc/lex.cにおけるGO386のパースロジックの変更
src/cmd/gc/lex.cはGoコンパイラの字句解析器の一部であり、ビルド時に設定されるGO386の値に基づいて、コンパイラがSSE命令を使用するかどうかを決定します。
変更前:
use_sse = strcmp(getgo386(), "sse") == 0;
変更後:
if(thechar == '8') { // '8' corresponds to GOARCH=386
p = getgo386();
if(strcmp(p, "387") == 0)
use_sse = 0;
else if(strcmp(p, "sse2") == 0)
use_sse = 1;
else
sysfatal("unsupported setting GO386=%s", p);
}
この変更により、コンパイラはGO386の値として"sse"ではなく"sse2"を期待するようになります。
GO386="387"の場合、use_sseは0となり、SSE/SSE2命令は使用されません。GO386="sse2"の場合、use_sseは1となり、コンパイラはSSE2命令を利用した最適化を行います。- これら以外の値が設定された場合は、致命的なエラー(
sysfatal)が発生し、サポートされていない設定であることをユーザーに通知します。
この変更は、コンパイラがGO386の値に基づいて、生成するアセンブリコードにSSE2命令を含めるかどうかを制御するための重要な部分です。
影響
この変更は、主に32ビットx86(GOARCH=386)向けのGoバイナリのビルドに影響を与えます。
- 性能向上: 現代のCPUでビルドする場合、デフォルトでSSE2が有効になるため、浮動小数点演算や一部のメモリ操作が高速化され、Goアプリケーションの実行性能が向上する可能性があります。
- 互換性: 非常に古いCPU(SSE2をサポートしないPentium III以前のプロセッサなど)でGoバイナリを実行しようとすると、
GO386=sse2でビルドされたバイナリは実行できない可能性があります。しかし、そのような環境は現在では非常に稀であり、Goのターゲット環境としては通常考慮されません。 - ビルドの明確化:
GO386=sse2というより正確な記述により、ビルド設定が何を意味するのかが明確になります。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルとコードの変更点は以下の通りです。
-
src/cmd/dist/a.h:bool cansse(void);がbool cansse2(void);に変更。distコマンドのヘッダーファイルで、CPU機能検出関数の宣言が更新されました。
-
src/cmd/dist/build.c:init()関数内で、GO386が未設定の場合のデフォルト値決定ロジックが変更。if(cansse())がif(cansse2())に変更。bwritestr(&b, "sse");がbwritestr(&b, "sse2");に変更。- これにより、デフォルトでSSE2のサポートがチェックされ、
GO386にsse2が設定されるようになりました。
-
src/cmd/dist/plan9.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Plan 9向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/dist/unix.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Unix系OS向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/dist/windows.c:bool cansse(void)関数がbool cansse2(void)にリネーム。- Windows向けのCPU機能検出ロジックの関数名が変更されました。
-
src/cmd/gc/lex.c:main()関数内で、GO386の値に基づいてuse_sseフラグを設定するロジックが変更。use_sse = strcmp(getgo386(), "sse") == 0;が削除。GOARCH=386の場合(thechar == '8')、getgo386()で取得した値が"387"ならuse_sse = 0、"sse2"ならuse_sse = 1に設定されるようになりました。- サポートされていない
GO386の値が検出された場合にsysfatalでエラーを出すロジックが追加されました。
コアとなるコードの解説
src/cmd/dist/a.h
このファイルは、Goのビルドツールであるdistコマンドが使用する共通のヘッダーファイルです。cansse()からcansse2()への変更は、このヘッダーで宣言されているCPU機能検出関数の名前が、より正確なSSE2のチェックを反映するように更新されたことを示しています。
src/cmd/dist/build.c
このファイルは、Goのビルドプロセスを制御するdistコマンドの主要な部分です。init()関数は、ビルド環境の初期化を担当し、その中でGO386環境変数のデフォルト値を設定します。
変更されたコードブロックは、GO386がユーザーによって明示的に設定されていない場合に実行されます。
if(b.len == 0) { // GO386が設定されていない場合
if(cansse2()) // SSE2が利用可能かチェック
bwritestr(&b, "sse2"); // 利用可能なら "sse2" を設定
else
bwritestr(&b, "387"); // 利用不可なら "387" を設定
}
このロジックにより、現代のCPUでは自動的にGO386=sse2が選択され、コンパイラがSSE2命令を利用した最適化を行うようになります。
src/cmd/dist/plan9.c, src/cmd/dist/unix.c, src/cmd/dist/windows.c
これらのファイルは、それぞれPlan 9、Unix系OS、Windowsといった異なるプラットフォームにおけるCPU機能検出の実装を含んでいます。cansse()関数がcansse2()にリネームされたのは、これらの関数が実際にSSE2のサポートをチェックするようになったことを明確にするためです。
例えば、src/cmd/dist/unix.cやsrc/cmd/dist/windows.cでは、CPUID命令(__cpuidまたはcpuid関数を通じて)を使用してCPUの機能フラグを読み取り、SSE2のサポートを示すビット(通常はEDXレジスタのビット26)がセットされているかを確認します。
src/cmd/gc/lex.c
このファイルはGoコンパイラの字句解析器の一部であり、コンパイル時にGO386の値に基づいてuse_sseという内部フラグを設定します。このフラグは、コンパイラのバックエンドがSSE/SSE2命令を生成するかどうかを制御します。
変更されたコードブロックは、GOARCHが386(thechar == '8')の場合に実行されます。
if(thechar == '8') { // GOARCH=386の場合
p = getgo386(); // GO386の値を取得
if(strcmp(p, "387") == 0) // "387" ならSSEを使わない
use_sse = 0;
else if(strcmp(p, "sse2") == 0) // "sse2" ならSSEを使う
use_sse = 1;
else
sysfatal("unsupported setting GO386=%s", p); // それ以外はエラー
}
このロジックにより、コンパイラはGO386の値が"sse2"である場合にのみSSE2命令を生成するようになり、"sse"という古い値はサポートされなくなりました。これにより、コンパイラの動作とビルドシステムの意図がより密接に連携するようになります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Goの環境変数に関するドキュメント: https://go.dev/doc/install/source#environment (このコミット時点では古い情報である可能性がありますが、概念は共通です)
- GoのIssueトラッカー (このコミットに関連する議論があるかもしれません): https://github.com/golang/go/issues
参考にした情報源リンク
- Streaming SIMD Extensions (SSE) - Wikipedia: https://ja.wikipedia.org/wiki/Streaming_SIMD_Extensions
- Streaming SIMD Extensions 2 (SSE2) - Wikipedia: https://ja.wikipedia.org/wiki/Streaming_SIMD_Extensions_2
- CPUID - Wikipedia: https://ja.wikipedia.org/wiki/CPUID
- Goのビルドシステムに関する一般的な情報 (Goのソースコードや関連するブログ記事、フォーラムの議論など)
grep sse2 /proc/cpuinfoおよびsysctl hw.optional.sse2のコマンド出力例に関する情報 (一般的なLinux/macOSのドキュメントやフォーラム)