LLVM言語リファレンスマニュアル

概要

このドキュメントは、LLVMアセンブリ言語のリファレンスマニュアルです。LLVMは、型安全性、低レベル操作、柔軟性、および「すべて」の高レベル言語を明確に表現する能力を提供する、静的単一代入(SSA)ベースの表現です。これは、LLVMコンパイル戦略のすべてのフェーズで使用される共通のコード表現です。

はじめに

LLVMのコード表現は、3つの異なる形式で使用できるように設計されています。インメモリコンパイラIRとして、オンディスクのビットコード表現(ジャストインタイムコンパイラによる高速ロードに適しています)、および人間が読めるアセンブリ言語表現です。これにより、LLVMは効率的なコンパイラ変換と分析のための強力な中間表現を提供すると同時に、変換をデバッグおよび視覚化する自然な手段を提供できます。LLVMの3つの異なる形式はすべて同等です。このドキュメントでは、人間が読める表現と表記について説明します。

LLVMの表現は、表現力豊かで、型付きで、拡張可能でありながら、軽量で低レベルであることを目指しています。高レベルのアイデアを(マイクロプロセッサが「ユニバーサルIR」であるように、多くのソース言語をそれにマップできるように)明確にマップできるほど低いレベルにあることで、ある種の「ユニバーサルIR」になることを目指しています。型情報を提供することで、LLVMは最適化のターゲットとして使用できます。たとえば、ポインタ解析を通じて、Cの自動変数が現在の関数の外部でアクセスされないことを証明できるため、メモリ位置ではなく単純なSSA値に昇格させることができます。

整形式

このドキュメントは、「整形式」のLLVMアセンブリ言語について説明していることに注意することが重要です。パーサーが受け入れるものと「整形式」と見なされるものには違いがあります。たとえば、次の命令は構文的には問題ありませんが、整形式ではありません。

%x = add i32 1, %x

%xの定義は、そのすべての使用を支配していないためです。LLVMインフラストラクチャは、LLVMモジュールが整形式であることを検証するために使用できる検証パスを提供します。このパスは、入力アセンブリの解析後にパーサーによって自動的に実行され、ビットコードを出力する前にオプティマイザーによって実行されます。検証パスによって指摘された違反は、変換パスまたはパーサーへの入力にバグがあることを示します。

構文

識別子

LLVM識別子には、グローバルとローカルの2つの基本的なタイプがあります。グローバル識別子(関数、グローバル変数)は、'@'文字で始まります。ローカル識別子(レジスタ名、型)は、'%'文字で始まります。さらに、目的の異なる3つの異なる形式の識別子があります。

  1. 名前付きの値は、接頭辞付きの文字列として表現されます。たとえば、%foo@DivisionByZero%a.really.long.identifier。実際に使用される正規表現は、「[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*」です。名前に他の文字が必要な識別子は、引用符で囲むことができます。特殊文字は、16進数で文字のASCIIコードを表す"\xx"を使用してエスケープできます。このようにして、引用符自体でも、任意の文字を名前の値に使用できます。"\01"接頭辞をグローバル値で使用して、マングリングを抑制できます。

  2. 名前のない値は、接頭辞付きの符号なし数値として表現されます。たとえば、%12@2%44

  3. 定数。これについては、以下の「定数」セクションで説明します。

LLVMでは、値が接頭辞で始まる必要があります。これには2つの理由があります。コンパイラは予約語との名前の衝突を心配する必要がなく、予約語のセットは将来、ペナルティなしで拡張できます。さらに、名前のない識別子を使用すると、コンパイラはシンボルテーブルの競合を回避する必要なく、一時変数をすばやく作成できます。

LLVMの予約語は、他の言語の予約語と非常によく似ています。さまざまなオペコード(「add」、「bitcast」、「ret」など)、プリミティブ型名(「void」、「i32」など)などのキーワードがあります。これらの予約語は、変数名と競合することはできません。予約語はいずれも接頭辞文字('%'または'@')で始まらないためです。

以下に、整数変数「%X」に8を掛けるLLVMコードの例を示します。

簡単な方法

%result = mul i32 %X, 8

強度削減後

%result = shl i32 %X, 3

難しい方法

%0 = add i32 %X, %X           ; yields i32:%0
%1 = add i32 %0, %0           ; yields i32:%1
%result = add i32 %1, %1

この%Xに8を掛ける最後の方法は、LLVMのいくつかの重要な字句機能を説明しています。

  1. コメントは「;」で区切られ、行末まで続きます。

  2. 計算の結果が名前付きの値に割り当てられていない場合、名前のない一時変数が作成されます。

  3. デフォルトでは、名前のない一時変数は順次番号付けされます(関数ごとにインクリメントされるカウンタを使用し、0から開始)。ただし、一時番号を明示的に指定する場合は、番号をスキップすることが許可されています。

    基本ブロックと名前のない関数パラメータがこの番号付けに含まれることに注意してください。たとえば、エントリ基本ブロックにラベル名が与えられておらず、すべての関数パラメータに名前が付けられている場合、0という番号が付けられます。

また、このドキュメントで従う規則も示しています。命令を示すときは、生成された値の型と名前を定義するコメントを命令に続けます。

文字列定数

LLVMプログラムの文字列は、"文字で区切られます。文字列内では、すべてのバイトはリテラルとして扱われます。ただし、エスケープを開始する\文字と、文字列を終了する最初の"文字は例外です。

エスケープには2種類あります。

  • \\は、単一の\文字を表します。

  • \の後に2つの16進数文字(0〜9、a〜f、またはA〜F)が続くと、指定された値を持つバイトを表します(たとえば、x00はnullバイトを表します)。

"文字を表現するには、\22を使用します。(\"を使用すると、末尾に\が付いた文字列で終了します。)

改行は文字列定数を終端しません。文字列は複数行にまたがることができます。

文字列定数(例えば、その文字エンコーディング)の解釈は、コンテキストに依存します。

高レベル構造

モジュール構造

LLVMプログラムは、それぞれが入力プログラムの翻訳単位であるModuleで構成されています。各モジュールは、関数、グローバル変数、およびシンボルテーブルエントリで構成されています。モジュールはLLVMリンカーで結合でき、関数(およびグローバル変数)の定義をマージし、前方宣言を解決し、シンボルテーブルエントリをマージします。以下は、「hello world」モジュールの例です。

; Declare the string constant as a global constant.
@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"

; External declaration of the puts function
declare i32 @puts(ptr nocapture) nounwind

; Definition of main function
define i32 @main() {
  ; Call puts function to write out the string to stdout.
  call i32 @puts(ptr @.str)
  ret i32 0
}

; Named metadata
!0 = !{i32 42, null, !"string"}
!foo = !{!0}

この例は、「.str」という名前のグローバル変数、「puts」関数の外部宣言、「main」の関数定義、および名前付きメタデータfoo」で構成されています。

一般に、モジュールはグローバル値のリストで構成されています(関数とグローバル変数の両方がグローバル値です)。グローバル値はメモリロケーションへのポインタ(この場合は、charの配列へのポインタと関数へのポインタ)で表され、以下のリンケージタイプのいずれかを持っています。

リンケージタイプ

すべてのグローバル変数と関数は、以下のいずれかのリンケージタイプを持ちます。

private

private」リンケージを持つグローバル値は、現在のモジュール内のオブジェクトによってのみ直接アクセス可能です。特に、privateグローバル値を持つコードをモジュールにリンクすると、衝突を避けるために必要に応じてprivateが名前変更される可能性があります。シンボルはモジュールに対してprivateであるため、すべての参照を更新できます。これは、オブジェクトファイルのシンボルテーブルには表示されません。

internal

privateと同様ですが、値はオブジェクトファイル内でローカルシンボル(ELFの場合にはSTB_LOCAL)として表示されます。これは、Cの「static」キーワードの概念に対応します。

available_externally

available_externally」リンケージを持つグローバルは、LLVMモジュールに対応するオブジェクトファイルには決して出力されません。リンカーの観点からは、available_externallyグローバルは外部宣言と同等です。これらは、モジュールの外部にあることがわかっているグローバルの定義の知識に基づいて、インライン化やその他の最適化が行われるようにするために存在します。available_externallyリンケージを持つグローバルは、自由に破棄することができ、インライン化やその他の最適化が可能です。このリンケージタイプは、宣言ではなく定義でのみ許可されています。

linkonce

linkonce」リンケージを持つグローバルは、リンクが発生したときに同じ名前の他のグローバルとマージされます。これは、インライン関数、テンプレート、またはそれを使用する各翻訳単位で生成する必要があるコードを実装するために使用できますが、本体は後でより決定的な定義で上書きされる可能性があります。参照されていないlinkonceグローバルは破棄される可能性があります。linkonceリンケージは、この関数の定義がプログラム内の決定的な定義であるかどうか、またはより強力な定義によって上書きされるかどうかを把握していないため、実際にはオプティマイザーがこの関数の本体を呼び出し元にインライン化することを許可していないことに注意してください。インライン化やその他の最適化を有効にするには、「linkonce_odr」リンケージを使用します。

weak

weak」リンケージは、linkonceリンケージと同じマージセマンティクスを持っています。ただし、参照されていないweakリンケージを持つグローバルは破棄されない場合があります。これは、Cソースコードで「weak」と宣言されたグローバルに使用されます。

common

common」リンケージは、「weak」リンケージに最も似ていますが、グローバルスコープでの「int X;」などのCの仮定義に使用されます。「common」リンケージを持つシンボルは、weak シンボルと同じ方法でマージされ、参照されていない場合は削除できません。commonシンボルは明示的なセクションを持つことができず、ゼロ初期化子を持つ必要があり、「定数」としてマークすることはできません。関数とエイリアスは共通リンケージを持つことができません。

appending

appending」リンケージは、配列型のポインタであるグローバル変数にのみ適用できます。appendingリンケージを持つ2つのグローバル変数がリンクされると、2つのグローバル配列が連結されます。これは、.oファイルがリンクされるときに、同じ名前を持つ「セクション」をシステムリンカーが連結するのと同じ、LLVMのタイプセーフな相当物です。

残念ながら、これは.oファイルのどの機能にも対応していないため、llvmが特別に解釈するllvm.global_ctorsのような変数にのみ使用できます。

extern_weak

このリンケージのセマンティクスは、ELFオブジェクトファイルモデルに従います。シンボルはリンクされるまで弱く、リンクされていない場合、シンボルは未定義の参照ではなくnullになります。

linkonce_odr, weak_odr

odrサフィックスは、指定された名前で定義されたすべてのグローバルが、C++の「1つの定義ルール」(「ODR」)に沿って同等であることを示します。非公式には、これは関数のインライン化や定数のロードの折りたたみが可能であることを意味します。

形式的には、次の定義を使用します。odr関数が呼び出されると、実行する定義のいずれかが非決定的に選択されます。odr変数の場合、値のいずれかのバイトがすべての初期化子で等しくない場合、そのバイトはpoison値です。エイリアスとifuncの場合は、基になる関数または変数にルールを適用します。

これらのリンケージタイプは、それ以外の場合は非odrバージョンと同じです。

external

上記の識別子のいずれも使用されていない場合、グローバルは外部から可視になります。つまり、リンケージに参加し、外部シンボル参照を解決するために使用できます。

グローバル変数または関数の宣言が、externalまたはextern_weak以外のリンケージタイプを持つことは違法です。

呼び出し規約

LLVM 関数呼び出し、およびinvokeは、すべて呼び出しに対してオプションの呼び出し規約を指定できます。動的な呼び出し元/呼び出し先のペアの呼び出し規約は一致する必要があります。そうでない場合、プログラムの動作は未定義になります。次の呼び出し規約はLLVMでサポートされており、今後さらに追加される可能性があります。

ccc” - C呼び出し規約

この呼び出し規約(他の呼び出し規約が指定されていない場合のデフォルト)は、ターゲットのC呼び出し規約と一致します。この呼び出し規約は、可変引数関数呼び出しをサポートし、関数の宣言されたプロトタイプと実装された宣言におけるいくつかの不一致を許容します(通常のCと同様)。

fastcc” - 高速呼び出し規約

この呼び出し規約は、可能な限り呼び出しを高速化しようとします(たとえば、レジスタに渡すなど)。この呼び出し規約では、ターゲットは、外部で指定されたABI(アプリケーションバイナリインターフェイス)に準拠する必要なく、ターゲットの高速コードを生成するために必要なあらゆるトリックを使用できます。末尾呼び出しは、この規約、tailcc、GHC、またはHiPE規約を使用した場合にのみ最適化できます。この呼び出し規約は可変引数をサポートしておらず、すべての呼び出し先のプロトタイプは関数定義のプロトタイプと正確に一致する必要があります。

coldcc” - コールド呼び出し規約

この呼び出し規約は、呼び出しが一般的に実行されないという前提の下で、呼び出し元のコードを可能な限り効率的にしようとします。そのため、これらの呼び出しでは、呼び出し元側のライブ範囲を壊さないように、すべてのレジスタが保持されることがよくあります。この呼び出し規約は可変引数をサポートしておらず、すべての呼び出し先のプロトタイプは関数定義のプロトタイプと正確に一致する必要があります。さらに、インライナーはこのような関数呼び出しをインライン化の対象とは見なしません。

ghccc” - GHC規約

この呼び出し規約は、Glasgow Haskell Compiler(GHC)で使用するために特別に実装されています。Callee Saveレジスタを無効にすることで、極端なまでにレジスタにすべてを渡します。この呼び出し規約は、安易に使用すべきではなく、関数型プログラミング言語を実装するときによく使用されるレジスタピンニングパフォーマンステクニックの代替などの特定の状況でのみ使用する必要があります。現時点では、X86、AArch64、およびRISCVのみがこの規約をサポートしています。以下の制限があります。

  • X86-32では、最大4ビット型のパラメーターのみがサポートされています。浮動小数点型はサポートされていません。

  • X86-64では、最大10ビット型のパラメーターと6つの浮動小数点パラメーターがサポートされています。

  • AArch64では、最大4つの32ビット浮動小数点パラメーター、4つの64ビット浮動小数点パラメーター、および10ビット型のパラメーターがサポートされています。

  • RISCV64は、最大11ビット型のパラメーター、4つの32ビット浮動小数点パラメーター、および4つの64ビット浮動小数点パラメーターをサポートしています。

この呼び出し規約は、末尾呼び出しの最適化をサポートしていますが、呼び出し元と呼び出し先の両方が使用している必要があります。

cc 11” - HiPE呼び出し規約

この呼び出し規約は、High-Performance Erlang(HiPE)コンパイラー、つまりEricssonのオープンソースErlang/OTPシステムのネイティブコードコンパイラーで使用するために特別に実装されています。通常のC呼び出し規約よりも多くのレジスタを引数渡しに使用し、Callee-Savedレジスタは定義しません。この呼び出し規約は、末尾呼び出しの最適化を適切にサポートしていますが、呼び出し元と呼び出し先の両方がそれを使用している必要があります。GHCの規約と同様に、頻繁にアクセスされるランタイムコンポーネントを特定のハードウェアレジスタに固定するためのレジスタピンニングメカニズムを使用します。現時点では、X86のみがこの規約をサポートしています(32ビットと64ビットの両方)。

anyregcc” - コードパッチ用の動的呼び出し規約

これは、呼び出し箇所で任意のコードシーケンスをインプレースでパッチすることをサポートする特別な規約です。この規約は、呼び出し引数をレジスタに強制的に入れるものの、それらを動的に割り当てることを可能にします。これは現在、llvm.experimental.patchpoint への呼び出しでのみ使用できます。なぜなら、この組み込み関数だけが、その引数の位置をサイドテーブルに記録するからです。LLVM におけるスタックマップとパッチポイントを参照してください。

preserve_mostcc」- PreserveMost 呼び出し規約

この呼び出し規約は、呼び出し元のコードをできる限り邪魔しないように試みます。この規約は、引数と戻り値の渡し方に関して、C 呼び出し規約と全く同じように動作しますが、呼び出し元/呼び出し先で保存されるレジスタの異なるセットを使用します。これにより、呼び出し元で呼び出しの前後に大規模なレジスタセットを保存および復元する負担が軽減されます。引数が呼び出し先で保存されるレジスタで渡される場合、それらは呼び出し先によって呼び出しをまたいで保存されます。これは、呼び出し先で保存されるレジスタで返される値には適用されません。

  • X86-64 では、呼び出し先は、R11 と戻り値レジスタ(存在する場合)を除くすべての汎用レジスタを保存します。R11 はスクラッチレジスタとして使用できます。浮動小数点レジスタ(XMM/YMM)の扱いは、OS の C 呼び出し規約に一致します。ほとんどのプラットフォームでは、それらは保存されず、呼び出し元によって保存される必要がありますが、Windows では xmm6-xmm15 が保存されます。

  • AArch64 では、呼び出し先は、X0-X8 および X16-X18 を除くすべての汎用レジスタを保存します。

この規約の背後にある考え方は、ホットパスとコールドパスを持つランタイム関数への呼び出しをサポートすることです。ホットパスは通常、多くのレジスタを使用しない小さなコードです。コールドパスは、別の関数を呼び出す必要がある可能性があり、したがって、呼び出し元によってすでに保存されていない、呼び出し元で保存されるレジスタのみを保存する必要があります。PreserveMost 呼び出し規約は、呼び出し元/呼び出し先で保存されるレジスタという点では cold 呼び出し規約と非常によく似ていますが、異なるタイプの関数呼び出しに使用されます。coldcc は、めったに実行されない関数呼び出し用ですが、preserve_mostcc 関数呼び出しは、ホットパスにあり、頻繁に実行されることが意図されています。さらに、preserve_mostcc は、インライナーによる関数呼び出しのインライン化を妨げません。

この呼び出し規約は、将来のバージョンの ObjectiveC ランタイムで使用される予定であり、したがって、現時点ではまだ実験的とみなされるべきです。この規約は、ObjectiveC ランタイムへの特定のランタイム呼び出しを最適化するために作成されましたが、このランタイムに限定されるものではなく、将来、他のランタイムでも使用される可能性があります。現在の実装は X86-64 のみをサポートしていますが、将来、より多くのアーキテクチャをサポートする予定です。

preserve_allcc」- PreserveAll 呼び出し規約

この呼び出し規約は、呼び出し元のコードを PreserveMost 呼び出し規約よりもさらに邪魔しないように試みます。この呼び出し規約も、引数と戻り値の渡し方に関して C 呼び出し規約と全く同じように動作しますが、呼び出し元/呼び出し先で保存されるレジスタの異なるセットを使用します。これにより、呼び出し元で呼び出しの前後に大規模なレジスタセットを保存および復元する負担が軽減されます。引数が呼び出し先で保存されるレジスタで渡される場合、それらは呼び出し先によって呼び出しをまたいで保存されます。これは、呼び出し先で保存されるレジスタで返される値には適用されません。

  • X86-64 では、呼び出し先は、R11 を除くすべての汎用レジスタを保存します。R11 はスクラッチレジスタとして使用できます。さらに、すべての浮動小数点レジスタ(XMM/YMM)も保存します。

  • AArch64 では、呼び出し先は、X0-X8 および X16-X18 を除くすべての汎用レジスタを保存します。さらに、V8-V31 SIMD - 浮動小数点レジスタの下位 128 ビットも保存します。

この規約の背後にある考え方は、他の関数を呼び出す必要がないランタイム関数への呼び出しをサポートすることです。

この呼び出し規約は、PreserveMost 呼び出し規約と同様に、将来のバージョンの ObjectiveC ランタイムで使用される予定であり、現時点では実験的とみなされるべきです。

preserve_nonecc」- PreserveNone 呼び出し規約

この呼び出し規約は、どの汎用レジスタも保存しません。したがって、すべての汎用レジスタは呼び出し元で保存されるレジスタです。また、すべての汎用レジスタを引数の受け渡しに使用します。この属性は、汎用以外のレジスタ(X86 XMM/YMM の浮動小数点レジスタなど)には影響しません。汎用以外のレジスタは、引き続き標準の C 呼び出し規約に従います。現在、x86_64 および AArch64 のみが対象です。

cxx_fast_tlscc」- アクセス関数用の CXX_FAST_TLS 呼び出し規約

Clang は、C++ スタイルの TLS にアクセスするためのアクセス関数を生成します。アクセス関数には通常、エントリブロック、終了ブロック、および初回実行時に実行される初期化ブロックがあります。エントリブロックと終了ブロックは、いくつかの TLS IR 変数にアクセスでき、各アクセスはプラットフォーム固有のシーケンスに変換されます。

この呼び出し規約は、可能な限り多くのレジスタを保存する(エントリブロックと終了ブロックで構成される高速パスで保存されるすべてのレジスタ)ことで、呼び出し元のオーバーヘッドを最小限に抑えることを目的としています。

この呼び出し規約は、引数と戻り値の渡し方に関して、C 呼び出し規約と全く同じように動作しますが、呼び出し元/呼び出し先で保存されるレジスタの異なるセットを使用します。

各プラットフォームには独自の変換シーケンス、したがって独自の保存されるレジスタのセットがあるため、既存の PreserveMost を使用することはできません。

  • X86-64 では、呼び出し先は、RDI と RAX を除くすべての汎用レジスタを保存します。

tailcc」- テール呼び出し可能な呼び出し規約

この呼び出し規約は、末尾位置での呼び出しが常にテールコール最適化されるようにします。この呼び出し規約は fastcc と同等ですが、テールコールが可能な場合は常に生成されるという追加の保証があります。テールコールは、この規約、fastcc、GHC、または HiPE 規約が使用されている場合にのみ最適化できます。この呼び出し規約は可変長引数をサポートせず、すべての被呼び出し側のプロトタイプが関数定義のプロトタイプと完全に一致する必要があります。

swiftcc」- この呼び出し規約は Swift 言語で使用されます。
  • X86-64 では、RCX と R8 が追加の整数戻り値に使用でき、XMM2 と XMM3 が追加の FP/ベクター戻り値に使用できます。

  • iOS プラットフォームでは、AAPCS-VFP 呼び出し規約を使用します。

swifttailcc

この呼び出し規約は、ほとんどの点で swiftcc のようですが、tailcc のように必須のテールコールが可能になるように、被呼び出し側もスタックの引数領域をポップします。

cfguard_checkcc」- Windows コントロールフローガード(チェックメカニズム)

この呼び出し規約は、コントロールフローガードのチェック関数に使用されます。チェック関数への呼び出しは、間接呼び出しの前に挿入して、呼び出し先が有効な関数アドレスであるかどうかをチェックできます。チェック関数には戻り値はありませんが、アドレスが有効なターゲットでない場合は OS レベルのエラーをトリガーします。チェック関数によって保存されるレジスタのセットと、ターゲットアドレスを含むレジスタは、アーキテクチャ固有です。

  • X86 では、ターゲットアドレスは ECX で渡されます。

  • ARM では、ターゲットアドレスは R0 で渡されます。

  • AArch64 では、ターゲットアドレスは X15 で渡されます。

cc <n>」- 番号付き規約

任意の呼び出し規約は番号で指定でき、ターゲット固有の呼び出し規約を使用できます。ターゲット固有の呼び出し規約は 64 から始まります。

Pascal 規約やその他のよく知られたターゲットに依存しない規約をサポートするために、必要に応じてさらに多くの呼び出し規約を追加/定義できます。

可視性スタイル

すべてのグローバル変数と関数には、次のいずれかの可視性スタイルがあります

default」- デフォルトスタイル

ELF オブジェクトファイル形式を使用するターゲットでは、デフォルトの可視性とは、宣言が他のモジュールに表示され、共有ライブラリでは、宣言されたエンティティが上書きされる可能性があることを意味します。Darwin では、デフォルトの可視性とは、宣言が他のモジュールに表示されることを意味します。XCOFF では、デフォルトの可視性とは、明示的な可視性ビットが設定されないことを意味し、シンボルが他のモジュールに表示される(つまり、「エクスポート」される)かどうかは、主にリンカーに提供されるエクスポートリストに依存します。デフォルトの可視性は、言語の「外部リンケージ」に対応します。

hidden」- 非表示スタイル

非表示の可視性を持つオブジェクトの 2 つの宣言は、同じ共有オブジェクトにある場合、同じオブジェクトを参照します。通常、非表示の可視性は、シンボルが動的シンボルテーブルに配置されないことを示し、そのため、他のモジュール(実行可能ファイルまたは共有ライブラリ)はそれを直接参照できません。

protected」- 保護スタイル

ELF では、保護された可視性は、シンボルが動的シンボルテーブルに配置されるが、定義モジュール内の参照はローカルシンボルにバインドされることを示します。つまり、シンボルは別のモジュールによって上書きできません。

internal または private リンケージを持つシンボルは、default の可視性を持つ必要があります。

DLL ストレージクラス

すべてのグローバル変数、関数、およびエイリアスには、次のいずれかの DLL ストレージクラスを設定できます

dllimport

dllimport」を指定すると、コンパイラは、シンボルをエクスポートする DLL によって設定されたポインタへのグローバルポインタを介して関数または変数を参照します。Microsoft Windows ターゲットでは、ポインタ名は __imp_ と関数または変数名を組み合わせることで形成されます。

dllexport

Microsoft Windowsターゲットでは、「dllexport」を指定すると、コンパイラはDLL内にグローバルポインタへのポインタを提供します。これにより、dllimport属性を使って参照できるようになります。ポインタ名は、__imp_と関数名または変数名を組み合わせることで形成されます。XCOFFターゲットでは、dllexportは、シンボルが「exported」の可視性を使用して他のモジュールから見えるようにされ、リンカによってローダーセクションのシンボルテーブルに配置されることを示します。このストレージクラスはDLLインターフェースを定義するために存在するため、コンパイラ、アセンブラ、リンカは、それが外部から参照されており、シンボルを削除してはならないことを認識します。

internalまたはprivateリンケージを持つシンボルは、DLLストレージクラスを持つことはできません。

スレッドローカルストレージモデル

変数はthread_localとして定義できます。これは、変数がスレッド間で共有されない(各スレッドが変数の独立したコピーを持つ)ことを意味します。すべてのターゲットがスレッドローカル変数をサポートしているわけではありません。オプションで、TLSモデルを指定できます。

localdynamic

現在の共有ライブラリ内でのみ使用される変数用。

initialexec

動的にロードされないモジュール内の変数用。

localexec

実行可能ファイルで定義され、その内部でのみ使用される変数用。

明示的なモデルが指定されていない場合、「一般的な動的」モデルが使用されます。

これらのモデルはELF TLSモデルに対応しています。どの状況で異なるモデルが使用できるかについての詳細は、ELF Handling For Thread-Local Storageを参照してください。ターゲットは、指定されたモデルがサポートされていない場合、またはより適切なモデルを選択できる場合は、異なるTLSモデルを選択できます。

モデルはエイリアスで指定することもできますが、その場合、エイリアスへのアクセス方法のみを制御します。エイリアス対象には影響しません。

ELF TLSモデルのリンカサポートがないプラットフォームでは、-femulated-tlsフラグを使用して、GCC互換のエミュレートされたTLSコードを生成できます。

ランタイムプリエンプション指定子

グローバル変数、関数、エイリアスには、オプションのランタイムプリエンプション指定子を含めることができます。プリエンプション指定子が明示的に指定されていない場合、シンボルはdso_preemptableであると見なされます。

dso_preemptable

関数または変数が、ランタイム時にリンケージユニットの外部からのシンボルに置き換えられる可能性があることを示します。

dso_local

dso_localとしてマークされた関数または変数は、同じリンケージユニット内のシンボルに解決されるとコンパイラが想定できます。定義がこのコンパイルユニット内にない場合でも、直接アクセスが生成されます。

構造体型

LLVM IRでは、「識別された」構造体型と「リテラル」構造体型の両方を指定できます。リテラル型は構造的に一意になりますが、識別された型は一意になることはありません。不透明な構造体型を使用して、まだ利用できない型を前方宣言することもできます。

識別された構造体指定の例を以下に示します。

%mytype = type { %mytype*, i32 }

LLVM 3.0リリースより前は、識別された型は構造的に一意でした。最近のバージョンのLLVMでは、リテラル型のみが一意になります。

非整数ポインタ型

注:非整数ポインタ型は開発中のものであり、現時点では実験的なものと見なすべきです。

LLVM IRでは、フロントエンドが、特定ののアドレス空間のポインタをデータレイアウト文字列を使用して「非整数」として示すことをオプションで許可します。非整数ポインタ型は、未指定のビット単位表現を持つポインタを表します。つまり、整数表現はターゲットに依存したり、不安定(固定整数によってサポートされていない)であったりする可能性があります。

inttoptr命令とptrtoint命令は、整数(つまり通常の)ポインタの場合と同じセマンティクスを持ち、整数を対応するポインタ型に変換し、ポインタ型から整数に変換しますが、注意すべき追加の意味合いがあります。非整数ポインタのビット表現は安定していない可能性があるため、同じオペランドの2つの同一のキャストは、同じ値を返す場合と返さない場合があります。言い換えれば、非整数型への変換または非整数型からの変換は、実装定義の方法で環境の状態に依存します。

フロントエンドがキャスト後の特定の値を観察したい場合、生成されたIRは、実装定義の方法で基になる環境をフェンスする必要があります。(実際には、このような操作にはnoinlineルーチンが必要になる傾向があります。)

オプティマイザーの観点からは、非整数型のinttoptrptrtointは、1つの重要な例外を除いて、整数型の場合と同様です。オプティマイザーは、一般的に、そのようなキャストの新しい動的出現を挿入することはできません。新しいキャストが挿入された場合、オプティマイザーは、a)すべての可能な値が有効であることを保証するか、b)適切なフェンシングが挿入されることを保証する必要があります。適切なフェンシングは実装定義であるため、オプティマイザーは後者を実行できません。前者は、ptrtoint(v)-ptrtoint(v) == 0のような、一般的に期待される多くのプロパティが非整数型では成り立たないため、困難です。同様の制限は、llvm.ptrmaskなど、ポインタビットを調べる可能性のある組み込み関数にも適用されます。

非整数ポインタ(通常は属性またはメタデータを使用)に対してフロントエンドによって提供されるアライメント情報は、ポインタの可能なすべての表現に対して有効である必要があります。

グローバル変数

グローバル変数は、実行時ではなくコンパイル時に割り当てられるメモリ領域を定義します。

グローバル変数定義は初期化されている必要があります。

他の変換ユニットのグローバル変数も宣言できます。この場合、初期化子はありません。

グローバル変数には、オプションでリンケージ型を指定できます。

グローバル変数定義または宣言のいずれかには、配置される明示的なセクションを指定でき、オプションで明示的なアライメントを指定できます。変数宣言とその定義の明示的または推論されたセクション情報に不一致がある場合、結果の動作は未定義です。

変数はグローバルconstantとして定義できます。これは、変数の内容が決して変更されないことを示します(より良い最適化を可能にし、グローバルデータを実行可能ファイルの読み取り専用セクションに配置できるようにします)。ランタイム初期化が必要な変数は、変数へのストアがあるため、constantとしてマークできないことに注意してください。

LLVMでは、グローバルの最終的な定義がそうでない場合でも、グローバル変数の宣言を定数としてマークすることを明示的に許可します。この機能を使用すると、プログラムのわずかに優れた最適化が可能になりますが、言語定義によって、「定数」に基づく最適化が定義を含まない変換ユニットに対して有効であることが保証される必要があります。

SSA値として、グローバル変数は、プログラム内のすべての基本ブロックでスコープ内にある(つまり、支配する)ポインタ値を定義します。グローバル変数は常に、メモリ領域を記述しており、LLVMのすべてのメモリオブジェクトはポインタを介してアクセスされるため、その「コンテンツ」型へのポインタを定義します。

グローバル変数はunnamed_addrでマークできます。これは、アドレスは重要ではなく、内容のみが重要であることを示します。このようにマークされた定数は、同じ初期化子を持つ他の定数とマージできます。重要なアドレスを持つ定数は、unnamed_addr定数とマージできます。結果は、アドレスが重要な定数になります。

local_unnamed_addr属性が指定されている場合、アドレスはモジュール内で重要ではないことがわかっています。

グローバル変数は、ターゲット固有の番号付きアドレス空間に存在するように宣言できます。それらをサポートするターゲットの場合、アドレス空間は、最適化の実行方法や、変数へのアクセスに使用されるターゲット命令に影響を与える可能性があります。デフォルトのアドレス空間はゼロです。アドレス空間修飾子は、他の属性よりも前に記述する必要があります。

LLVMでは、グローバルに明示的なセクションを指定できます。ターゲットがそれをサポートしている場合、グローバルを指定されたセクションに出力します。さらに、ターゲットに必要なサポートがある場合、グローバルをcomdatに配置できます。

外部宣言には、明示的なセクションを指定できます。セクション情報は、この情報を使用するターゲットのためにLLVM IRで保持されます。セクション情報を外部宣言に添付することは、その定義が指定されたセクションにあるというアサーションです。定義が別のセクションにある場合、動作は未定義です。

LLVMでは、グローバル変数に対して明示的なコードモデルを指定できます。ターゲットが対応していれば、トランスレーションユニットのコンパイルに使用されたコードモデルを上書きして、指定されたコードモデルでグローバル変数を生成します。指定できる値は、「tiny」、「small」、「kernel」、「medium」、「large」です。将来的には、特定のコードモデルにきれいに当てはまらないグローバルデータのレイアウトを指定できるように拡張される可能性があります。

デフォルトでは、グローバル変数の初期化子は、モジュール内で定義されたグローバル変数が、グローバル初期化子の開始前に初期値から変更されないことを前提として最適化されます。これは、外部リンケージを持つ変数や、@llvm.used または dllexported 変数など、モジュール外部からアクセスできる可能性のある変数でも同様です。この前提は、変数に externally_initialized をマークすることで抑制できます。

グローバル変数には、明示的なアライメントを指定できます。アライメントは2のべき乗である必要があります。指定しない場合、またはアライメントがゼロに設定されている場合は、グローバル変数のアライメントは、ターゲットが都合が良いと感じる値に設定されます。明示的なアライメントが指定された場合、グローバル変数は正確にそのアライメントを持つように強制されます。ターゲットとオプティマイザは、グローバル変数にセクションが割り当てられている場合、グローバル変数を過剰にアラインすることはできません。この場合、追加のアライメントは観測可能になる可能性があります。たとえば、コードはグローバル変数がセクションに密にパックされていると仮定し、配列として反復処理しようとする可能性があり、アライメントパディングによってこの反復処理が中断されます。TLS変数の場合、モジュールフラグ MaxTLSAlign が存在する場合、アライメントを指定された値に制限します。オプティマイザは、これらの変数にそれ以上の強力なアライメントを課すことはできません。最大アライメントは 1 << 32 です。

グローバル変数の宣言、およびリンク時に置き換えられる可能性のある定義(linkonceweakextern_weakcommon リンケージ型)の場合、それが解決される定義の割り当てサイズとアライメントは、宣言または置き換え可能な定義のサイズとアライメント以上である必要があります。そうでない場合、動作は未定義です。

グローバル変数は、DLLストレージクラス、オプションのランタイムプリエンプション指定子、オプションのグローバル属性、およびオプションの添付されたメタデータのリストを持つこともできます。

変数とエイリアスは、スレッドローカルストレージモデルを持つことができます。

グローバル変数は、コンパイル時にサイズが不明なため、スケーラブルベクターを含むことはできません。複数の値を返すイントリンシックを容易にするために、構造体では許可されています。一般に、スケーラブルベクターを含む構造体は「サイズ指定」されたとは見なされず、ロード、ストア、アロカ、またはGEPでは使用できません。この規則の唯一の例外は、同じ型のスケーラブルベクターを含む構造体の場合です(例えば、{<vscale x 2 x i32>, <vscale x 2 x i32>} は同じ型を含み、{<vscale x 2 x i32>, <vscale x 2 x i64>} は含みません)。これらの種類の構造体(同種のスケーラブルベクター構造体と呼ぶことができます)はサイズ指定されていると見なされ、ロード、ストア、アロカで使用できますが、GEPでは使用できません。

toc-data 属性が設定されたグローバル変数は、XCOFFのTOCに格納されます。それらのアライメントは、TOCエントリのアライメントよりも大きくありません。最適化によって、TOCオーバーフローを軽減するために、それらのアライメントを大きくしないでください。

構文

@<GlobalVarName> = [Linkage] [PreemptionSpecifier] [Visibility]
                   [DLLStorageClass] [ThreadLocal]
                   [(unnamed_addr|local_unnamed_addr)] [AddrSpace]
                   [ExternallyInitialized]
                   <global | constant> <Type> [<InitializerConstant>]
                   [, section "name"] [, partition "name"]
                   [, comdat [($name)]] [, align <Alignment>]
                   [, code_model "model"]
                   [, no_sanitize_address] [, no_sanitize_hwaddress]
                   [, sanitize_address_dyninit] [, sanitize_memtag]
                   (, !name !N)*

たとえば、以下は、初期化子、セクション、およびアライメントを持つ番号付きアドレス空間にグローバルを定義します。

@G = addrspace(5) constant float 1.0, section "foo", align 4

次の例は、グローバル変数を宣言しているだけです。

@G = external global i32

次の例は、large コードモデルを使用してグローバル変数を定義します。

@G = internal global i32 0, code_model "large"

次の例は、initialexec TLSモデルを使用してスレッドローカルグローバルを定義します。

@G = thread_local(initialexec) global i32 0, align 4

関数

LLVM関数定義は、「define」キーワード、オプションのリンケージ型、オプションのランタイムプリエンプション指定子、オプションの可視性スタイル、オプションのDLLストレージクラス、オプションの呼び出し規約、オプションのunnamed_addr属性、戻り型、戻り型に対するオプションのパラメーター属性、関数名、(場合によっては空の)引数リスト(それぞれにオプションのパラメーター属性付き)、オプションの関数属性、オプションのアドレス空間、オプションのセクション、オプションのパーティション、オプションのアライメント、オプションのcomdat、オプションのガベージコレクター名、オプションのプレフィックス、オプションのプロローグ、オプションのパーソナリティ、オプションの添付されたメタデータのリスト、開始の中かっこ、基本ブロックのリスト、および終了の中かっこで構成されます。

構文

define [linkage] [PreemptionSpecifier] [visibility] [DLLStorageClass]
       [cconv] [ret attrs]
       <ResultType> @<FunctionName> ([argument list])
       [(unnamed_addr|local_unnamed_addr)] [AddrSpace] [fn Attrs]
       [section "name"] [partition "name"] [comdat [($name)]] [align N]
       [gc] [prefix Constant] [prologue Constant] [personality Constant]
       (!name !N)* { ... }

引数リストは、引数が次の形式である引数のコンマ区切りのシーケンスです。

構文

<type> [parameter Attrs] [name]

LLVM関数宣言は、「declare」キーワード、オプションのリンケージ型、オプションの可視性スタイル、オプションのDLLストレージクラス、オプションの呼び出し規約、オプションの unnamed_addr または local_unnamed_addr 属性、オプションのアドレス空間、戻り型、戻り型に対するオプションのパラメーター属性、関数名、場合によっては空の引数リスト、オプションのアライメント、オプションのガベージコレクター名、オプションのプレフィックス、およびオプションのプロローグで構成されます。

構文

declare [linkage] [visibility] [DLLStorageClass]
        [cconv] [ret attrs]
        <ResultType> @<FunctionName> ([argument list])
        [(unnamed_addr|local_unnamed_addr)] [align N] [gc]
        [prefix Constant] [prologue Constant]

関数定義には、関数のCFG(制御フローグラフ)を形成する基本ブロックのリストが含まれています。各基本ブロックは、オプションでラベル(基本ブロックにシンボルテーブルエントリを与える)で始まり、命令とデバッグレコードのリストが含まれ、ターミネーター命令(分岐や関数リターンなど)で終わります。明示的なラベル名が提供されていない場合、ブロックには、名前のない一時変数に使用されるのと同じカウンターから次の値を使用して、暗黙的な番号付きラベルが割り当てられます(上記を参照)。たとえば、関数エントリブロックに明示的なラベルがない場合、「%0」というラベルが割り当てられ、次にそのブロックの最初の名前のない一時変数が「%1」になります。数値ラベルが明示的に指定されている場合、暗黙的に使用される数値ラベルと一致する必要があります。

関数内の最初の基本ブロックは、2つの点で特別です。関数へのエントリ時にすぐに実行され、先行する基本ブロックを持つことが許可されていません(つまり、関数のエントリブロックへの分岐は許可されていません)。ブロックには先行ブロックがないため、PHIノードを持つこともできません。

LLVMでは、関数に明示的なセクションを指定できます。ターゲットが対応している場合、指定されたセクションに関数を生成します。さらに、関数はCOMDATに配置できます。

関数には、明示的なアライメントを指定できます。存在しない場合、またはアライメントがゼロに設定されている場合、関数のアライメントは、ターゲットが都合が良いと感じる値に設定されます。明示的なアライメントが指定されている場合、関数には少なくともその程度のアライメントが強制されます。すべてのアライメントは2のべき乗である必要があります。

unnamed_addr属性が指定されている場合、アドレスは重要ではないことがわかっており、2つの同一の関数をマージできます。

local_unnamed_addr属性が指定されている場合、アドレスはモジュール内で重要ではないことがわかっています。

明示的なアドレス空間が指定されていない場合、datalayout文字列からプログラムのアドレス空間がデフォルトで使用されます。

エイリアス

エイリアスは、関数や変数とは異なり、新しいデータを作成しません。既存の位置に対する新しいシンボルとメタデータにすぎません。

エイリアスには名前と、グローバル値または定数式のいずれかであるエイリアシーがあります。

エイリアスは、オプションでリンケージタイプ、オプションでランタイムプリエンプション指定子、オプションで可視性スタイル、オプションでDLLストレージクラス、およびオプションでTLSモデルを持つことができます。

構文

@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
          [, partition "name"]

リンケージは、privateinternallinkonceweaklinkonce_odrweak_odrexternalavailable_externallyのいずれかである必要があります。一部のシステムリンカは、エイリアス化された弱いシンボルを正しく削除できない可能性があることに注意してください。

unnamed_addrではないエイリアスは、エイリアシー式と同じアドレスを持つことが保証されています。unnamed_addrなものは、同じコンテンツを指すことのみが保証されています。

local_unnamed_addr属性が指定されている場合、アドレスはモジュール内で重要ではないことがわかっています。

エイリアスは単なる2番目の名前であるため、いくつかの制限が適用され、その一部はオブジェクトファイルの生成時にのみチェックできます。

  • エイリアシーを定義する式は、アセンブリ時に計算可能である必要があります。単なる名前であるため、再配置は使用できません。

  • 式中のエイリアスは、中間エイリアスがオーバーライドされる可能性をオブジェクトファイルで表現できないため、weakであってはなりません。

  • エイリアスがavailable_externallyリンケージを持つ場合、エイリアシーはavailable_externallyなグローバル値である必要があります。そうでない場合、エイリアシーは式にできますが、式中のグローバル値は宣言にすることはできません。これは再配置が必要になるため、不可能です。

  • エイリアスまたはエイリアシーのいずれかが、リンク時または実行時にモジュール外のシンボルに置き換えられる可能性がある場合、動作が異なる可能性があるため、最適化によってエイリアスをエイリアシーに置き換えることはできません。エイリアスは、現在のモジュール内のコンテンツを指すことが保証された名前として使用できます。

IFuncs

IFuncsは、エイリアスと同様に、新しいデータや関数を作成しません。それらは、リゾルバー関数を呼び出すことによってランタイム時に解決される新しいシンボルにすぎません。

ELFプラットフォームでは、IFuncsはロード時に動的リンカによって解決されます。Mach-Oプラットフォームでは、.symbol_resolver関数によって低レベル化されます。これにより、最初に呼び出されたときに遅延的に呼び出し先が解決されます。

IFuncは、オプションでリンケージタイプとオプションで可視性スタイルを持つことができます。

構文

@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] ifunc <IFuncTy>, <ResolverTy>* @<Resolver>
          [, partition "name"]

Comdats

Comdat IRは、関連するセクションを表すオブジェクトファイルCOMDAT/セクショングループ機能へのアクセスを提供します。

Comdatsには、COMDATキーを表す名前と、2つの異なるオブジェクトファイルで同じキーを持つcomdatをリンカがどのように重複排除するかに関する入力を提供するための選択種別があります。comdatはユニットとして含めるか省略する必要があります。comdat全体を破棄することは許可されていますが、サブセットを破棄することはできません。

グローバルオブジェクトは、最大で1つのcomdatのメンバーになることができます。エイリアスは、エイリアシーが計算するのと同じCOMDAT(存在する場合)に配置されます。

構文

$<Name> = comdat SelectionKind

nodeduplicate以外の選択種別の場合、重複するcomdatの1つのみをリンカによって保持でき、残りのcomdatのメンバーは破棄する必要があります。次の選択種別がサポートされています

any

リンカは任意のCOMDATキーを選択できます。選択は任意です。

exactmatch

リンカは任意のCOMDATキーを選択できますが、セクションには同じデータが含まれている必要があります。

largest

リンカは、最大のCOMDATキーを含むセクションを選択します。

nodeduplicate

重複排除は実行されません。

samesize

リンカは任意のCOMDATキーを選択できますが、セクションには同じ量のデータが含まれている必要があります。

  • XCOFFおよびMach-OはCOMDATをサポートしていません。

  • COFFはすべての選択種別をサポートしています。nodeduplicate以外の選択種別では、非ローカルリンケージのCOMDATシンボルが必要です。

  • ELFは、anyおよびnodeduplicateをサポートしています。

  • WebAssemblyはanyのみをサポートしています。

COMDATキーのセクションが最大の場合にのみ関数が選択されるCOFF COMDATの例を次に示します

$foo = comdat largest
@foo = global i32 2, comdat($foo)

define void @bar() comdat($foo) {
  ret void
}

COFFオブジェクトファイルでは、これにより、@fooシンボルの内容を含む選択種別IMAGE_COMDAT_SELECT_LARGESTのCOMDATセクションと、最初のCOMDATセクションに関連付けられ、@barシンボルの内容を含む選択種別IMAGE_COMDAT_SELECT_ASSOCIATIVEの別のCOMDATセクションが作成されます。

構文糖として、名前がグローバル名と同じ場合は、$nameを省略できます

$foo = comdat any
@foo = global i32 2, comdat
@bar = global i32 3, comdat($foo)

グローバルオブジェクトのプロパティにはいくつかの制限があります。COFFをターゲットとする場合、グローバルオブジェクトまたはそのエイリアスは、COMDATグループと同じ名前を持っている必要があります。このオブジェクトの内容とサイズは、選択種別に応じて、リンク時にどのCOMDATグループが選択されるかを決定するために使用できます。オブジェクトの名前はCOMDATグループの名前と一致する必要があるため、グローバルオブジェクトのリンケージはローカルであってはなりません。ローカルシンボルは、シンボルテーブルで競合が発生した場合に名前が変更される可能性があります。

COMDATとセクション属性を組み合わせて使用すると、驚くべき結果が生じる可能性があります。たとえば

$foo = comdat any
$bar = comdat any
@g1 = global i32 42, section "sec", comdat($foo)
@g2 = global i32 42, section "sec", comdat($bar)

オブジェクトファイルの観点からは、これには同じ名前の2つのセクションを作成する必要があります。これは、両方のグローバル変数が異なるCOMDATグループに属しており、オブジェクトファイルレベルではCOMDATがセクションで表されるため、必要です。

グローバル変数や関数などの特定のIR構造は、COMDAT IRを使用して指定されたものに加えて、オブジェクトファイルでCOMDATを作成する可能性があることに注意してください。これは、コードジェネレーターがグローバル変数を個々のセクションで出力するように構成されている場合(たとえば、-data-sectionsまたは-function-sectionsllcに指定されている場合)に発生します。

名前付きメタデータ

名前付きメタデータは、メタデータのコレクションです。メタデータノード(ただしメタデータ文字列ではない)は、名前付きメタデータの唯一の有効なオペランドです。

  1. 名前付きメタデータは、メタデータプレフィックスを持つ文字列として表されます。メタデータ名のルールは識別子のルールと同じですが、引用符付きの名前は許可されていません。"\xx"タイプのエスケープは引き続き有効であり、これにより任意の文字を名前の一部にすることができます。

構文

; Some unnamed metadata nodes, which are referenced by the named metadata.
!0 = !{!"zero"}
!1 = !{!"one"}
!2 = !{!"two"}
; A named metadata.
!name = !{!0, !1, !2}

パラメーター属性

関数型の戻り値の型と各パラメーターには、関連付けられた一連のパラメーター属性を設定できます。パラメーター属性は、関数の結果またはパラメーターに関する追加情報を伝達するために使用されます。パラメーター属性は、関数型の一部ではなく、関数の一部と見なされるため、異なるパラメーター属性を持つ関数は、同じ関数型を持つことができます。

パラメーター属性は、指定された型に従う単純なキーワードです。複数のパラメーター属性が必要な場合は、スペースで区切ります。たとえば

declare i32 @printf(ptr noalias nocapture, ...)
declare i32 @atoi(i8 zeroext)
declare signext i8 @returns_signed_char()

関数結果の属性(nonnullsignext)は、結果の型の前に来ることに注意してください。

現在、次のパラメーター属性のみが定義されています

zeroext

これは、パラメーターまたは戻り値が、ターゲットのABIで要求される範囲まで、呼び出し元(パラメーターの場合)または呼び出し先(戻り値の場合)によってゼロ拡張される必要があることをコードジェネレーターに示します。

signext

これは、パラメーターまたは戻り値が、ターゲットのABI(通常は32ビット)で要求される範囲まで、呼び出し元(パラメーターの場合)または呼び出し先(戻り値の場合)によって符号拡張される必要があることをコードジェネレーターに示します。

inreg

これは、関数呼び出しまたは戻りのコードを出力する際に、このパラメーターまたは戻り値をターゲット依存の特別な方法で処理する必要があることを示します(通常、メモリではなくレジスターに入れることによってですが、一部のターゲットでは、2つの異なる種類のレジスターを区別するために使用します)。この属性の使用はターゲット固有です。

byval(<ty>)

これは、ポインターパラメーターを実際には関数に値で渡す必要があることを示します。この属性は、呼び出し元と呼び出し先の間にポインティーの隠しコピーが作成されることを意味するため、呼び出し先は呼び出し元の値を変更できません。この属性は、LLVMポインター引数でのみ有効です。これは通常、構造体と配列を値で渡すために使用されますが、スカラーへのポインターでも有効です。コピーは、呼び出し先ではなく呼び出し元に属すると見なされます(たとえば、readonly関数はbyvalパラメーターに書き込むべきではありません)。これは戻り値の有効な属性ではありません。

byval型引数は、メモリ内の値の型を示し、引数のポインティー型と同じである必要があります。

byval属性は、align属性でアラインメントを指定することもサポートしています。これは、形成するスタックスロットのアラインメントと、呼び出しサイトに指定されたポインターの既知のアラインメントを示します。アラインメントが指定されていない場合、コードジェネレーターはターゲット固有の仮定を行います。

byref(<ty>)

byref引数属性を使用すると、引数のポインティーメモリ型を指定できます。これはbyvalに似ていますが、コピーがどこにも作成されることや、引数がスタックに渡されることを意味しません。これは、ポインターがその型のストレージサイズまで参照解除可能であることを意味します。

byrefポインターへの書き込みを導入することは一般的に許可されていません。ポインターは任意のアドレス空間を持つことができ、読み取り専用である可能性があります。

これは戻り値の有効な属性ではありません。

byrefパラメーターのアラインメントは、byvalと同様に、align属性と組み合わせることで明示的に指定できます。アラインメントが指定されていない場合、コードジェネレーターはターゲット固有の仮定を行います。

これはABI制約を表すためのものであり、最適化のために推論されるものではありません。

preallocated(<ty>)

これは、ポインター引数が実際には関数に値渡しされるべきであり、ポインター引数の指す先のメモリが呼び出し命令の前に初期化済みであることを示します。この属性は、LLVMのポインター引数に対してのみ有効です。引数は、musttailではない呼び出しでは、適切なllvm.call.preallocated.argによって返された値、またはmusttail呼び出しでは対応する呼び出し元の引数である必要がありますが、コード生成中は無視されます。

preallocated属性を持つ引数を持つmusttailではない関数呼び出しは、"preallocated"オペランドバンドルを持つ必要があります。musttail関数呼び出しは、"preallocated"オペランドバンドルを持つことはできません。

preallocated属性は、引数が指す先の型と同じである必要がある型引数を必要とします。

preallocated属性は、align属性でアライメントを指定することもサポートしています。これは、形成するスタックスロットのアライメントと、呼び出しサイトに指定されたポインターの既知のアライメントを示します。アライメントが指定されていない場合、コードジェネレーターはターゲット固有の仮定を行います。

inalloca(<ty>)

inalloca引数属性を使用すると、呼び出し元は出力スタック引数のアドレスを取得できます。inalloca引数は、alloca命令によって生成されたスタックメモリへのポインターである必要があります。alloca、つまり引数の割り当ては、inallocaキーワードでタグ付けされている必要もあります。最後の引数のみがinalloca属性を持つことができ、その引数はメモリで渡されることが保証されます。

引数の割り当ては、呼び出しによって解放される可能性があるため、最大で1回の呼び出しで使用できます。inalloca属性は、inregnestsret、またはbyvalなどの引数の格納に影響を与える他の属性と組み合わせて使用することはできません。inalloca属性は、LLVMの大きな集約的な戻り値の暗黙的な低減も無効にします。つまり、フロントエンドの作成者はそれらをsretポインターで低減する必要があります。

呼び出しサイトに到達すると、引数の割り当ては、まだ有効な最も最近のスタック割り当てである必要があります。そうでない場合、動作は未定義です。引数の割り当て後、呼び出しサイトの前にスタック領域を追加で割り当てることは可能ですが、llvm.stackrestoreでクリアする必要があります。

inalloca属性は、引数が指す先の型と同じである必要がある型引数を必要とします。

この属性の使用方法の詳細については、InAlloca属性の設計と使用法を参照してください。

sret(<ty>)

これは、ポインター引数が、ソースプログラムでの関数の戻り値である構造体のアドレスを指定することを示します。このポインターは、呼び出し元によって有効であることが保証されている必要があります。構造体へのロードとストアは、被呼び出し側によってトラップせず、適切にアラインされていると想定される場合があります。これは、戻り値に対して有効な属性ではありません。

sret型引数は、メモリ内の型を指定します。これは引数の指す先の型と同じである必要があります。

elementtype(<ty>)

elementtype引数属性は、不透明なポインターと互換性のある方法で、ポインターの要素型を指定するために使用できます。

elementtype属性自体には、特定のセマンティクスはありません。ただし、特定の組み込み関数では、この属性が存在し、特定のセマンティクスを割り当てる必要がある場合があります。これは、個々の組み込み関数でドキュメント化されます。

属性は、組み込み呼び出しのポインター型の引数にのみ適用できます。非組み込み呼び出しに適用したり、関数宣言のパラメーターに適用したりすることはできません。不透明でないポインターの場合、elementtypeに渡される型は、ポインターの要素型と一致する必要があります。

align <n> または align(<n>)

これは、ポインター値またはポインターのベクターが指定されたアライメントを持つことを示します。ポインターのベクターに適用した場合、すべてのポインター(要素)が指定されたアライメントを持ちます。ポインター値が指定されたアライメントを持っていない場合は、代わりにpoison valueが返されるか、渡されます。align属性は、ポインターがアラインされていることを保証するために、noundef属性と組み合わせて使用する必要があります。そうでない場合、動作は未定義です。align 1は、byval、preallocatedではない引数には効果がないことに注意してください。

この属性は、byvalまたはpreallocated属性と組み合わされた場合、追加のセマンティクスを持ちます。これについては、そこで説明します。

noalias

これは、引数または戻り値に基づいたポインター値を介してアクセスされるメモリロケーションが、関数の実行中に、引数または戻り値に基づいていないポインター値を介してアクセスされないことを示します。この保証は、関数の実行中に何らかの手段で変更されたメモリロケーションに対してのみ有効です。戻り値の属性には、以下で説明する追加のセマンティクスもあります。呼び出し元は、これらの要件が満たされることを保証する責任を被呼び出し側と共有します。詳細については、エイリアス分析のNoAlias応答の説明を参照してください。

noaliasのこの定義は、関数引数のC99におけるrestrictの定義と意図的に似ています。

関数の戻り値の場合、C99のrestrictは意味がありませんが、LLVMのnoaliasは意味があります。さらに、戻り値のnoalias属性のセマンティクスは、関数引数で使用した場合の属性のセマンティクスよりも強力です。関数の戻り値では、noalias属性は、関数がシステムのメモリ割り当て関数のように動作し、呼び出し元がアクセスできる他のオブジェクトのストレージとは別の割り当てられたストレージへのポインターを返すことを示します。

nocapture

これは、被呼び出し側がポインターをキャプチャしないことを示します。これは、戻り値に対して有効な属性ではありません。この属性は、この引数で渡されたポインターの特定のコピーにのみ適用されます。呼び出し元は、同じポインターの2つのコピーを渡すことができ、1つにはnocaptureが注釈され、もう1つには注釈が付けられません。また、被呼び出し側は、注釈されていないパラメーターを介して有効にキャプチャできます。

define void @f(ptr nocapture %a, ptr %b) {
  ; (capture %b)
}

call void @f(ptr @glb, ptr @glb) ; well-defined
nofree

これは、被呼び出し側がポインター引数を解放しないことを示します。これは、戻り値に対して有効な属性ではありません。

nest

これは、ポインター引数がトランポリン組み込みを使用して削除できることを示します。これは、戻り値に対して有効な属性ではなく、1つのパラメーターにのみ適用できます。

returned

これは、関数が常に引数を戻り値として返すことを示します。これは、呼び出し元を生成するときに使用されるオプティマイザーおよびコードジェネレーターへのヒントであり、値の伝播、末尾呼び出しの最適化、および場合によってはレジスタの保存と復元の省略を可能にします。被呼び出し側を生成する際にはチェックまたは強制されません。パラメーターと関数の戻り値の型は、bitcast命令の有効なオペランドである必要があります。これは、戻り値に対して有効な属性ではなく、1つのパラメーターにのみ適用できます。

nonnull

これは、パラメーターまたは戻り値のポインターがnullではないことを示します。この属性は、ポインター型のパラメーターにのみ適用できます。これはLLVMによってチェックまたは強制されません。パラメーターまたは戻り値のポインターがnullの場合、代わりにpoison valueが返されるか、渡されます。nonnull属性は、ポインターがnullではないことを保証するために、noundef属性と組み合わせて使用する必要があります。そうでない場合、動作は未定義です。

dereferenceable(<n>)

これは、パラメーターまたは戻り値のポインターが逆参照可能であることを示します。この属性は、ポインター型のパラメーターにのみ適用できます。逆参照可能なポインターは、トラップのリスクなしに投機的にロードできます。逆参照可能であることがわかっているバイト数を括弧で囲んで指定する必要があります。バイト数が指す先の型のサイズよりも小さくても構いません。nonnull属性は逆参照可能性を意味しません(配列の末尾を越えた1つの要素へのポインターを考えてください)。ただし、dereferenceable(<n>)は、null_pointer_is_valid関数属性が存在する場合を除いて、addrspace(0)(これはデフォルトのアドレス空間です)でnonnullを意味します。nは正の数である必要があります。ポインターは適切に定義されている必要があり、そうでない場合は未定義の動作になります。これは、dereferenceable(<n>)noundefを意味することを示します。

dereferenceable_or_null(<n>)

これは、パラメーターまたは戻り値が、同時に非nullかつ非逆参照可能(最大<n>バイト)ではないことを示します。dereferenceable_or_null(<n>)でタグ付けされたすべての非nullポインターは、dereferenceable(<n>)です。アドレス空間0の場合、dereferenceable_or_null(<n>)は、ポインターがdereferenceable(<n>)またはnullのいずれかであることを意味し、他のアドレス空間ではdereferenceable_or_null(<n>)は、ポインターが少なくともdereferenceable(<n>)またはnullのいずれかであることを意味します(つまり、nulldereferenceable(<n>)の両方である可能性があります)。この属性は、ポインター型のパラメーターにのみ適用できます。

swiftself

これは、パラメーターがself/contextパラメーターであることを示します。これは、戻り値に対して有効な属性ではなく、1つのパラメーターにのみ適用できます。

swiftasync

これは、パラメータが非同期コンテキストパラメータであることを示し、このポインタを格納するためのターゲット固有の拡張フレームレコードの作成をトリガーします。これは戻り値に対して有効な属性ではなく、1つのパラメータにのみ適用できます。

swifterror

この属性は、Swiftのエラー処理をモデル化し、最適化することを目的としています。ポインタへのポインタ型またはポインタサイズの alloca を持つパラメータに適用できます。呼び出し箇所では、swifterror パラメータに対応する実引数は、swifterror alloca または呼び出し元の swifterror パラメータから取得する必要があります。swifterror 値(パラメータまたは alloca のいずれか)は、swifterror 引数としてロードおよび格納するか、または使用することのみができます。これは戻り値に対して有効な属性ではなく、1つのパラメータにのみ適用できます。

これらの制約により、呼び出し規約は、swifterror 変数をメモリに配置するのではなく、呼び出し境界で特定のレジスタに関連付けることで、swifterror 変数へのアクセスを最適化できます。これにより呼び出し規約が変更されるため、パラメータに swifterror 属性を使用する関数は、使用しない関数と ABI 互換性がありません。

これらの制約により、LLVM は、swifterror 引数が関数内で可視の他のメモリとエイリアスせず、引数として渡された swifterror alloca がエスケープしないと仮定することもできます。

immarg

これは、パラメータが即時値である必要があることを示します。これは、単純な即時整数または浮動小数点定数でなければなりません。undef または定数式は無効です。これは、組み込み宣言でのみ有効であり、呼び出し箇所や任意の関数には適用できません。

noundef

この属性は、パラメータと戻り値に適用されます。値の表現に未定義またはポイズンビットが含まれている場合、動作は未定義です。これは、型のストレージ表現によって導入されるパディングを指すものではないことに注意してください。

nofpclass(<テスト マスク>)

この属性は、浮動小数点型および浮動小数点型のベクター型、およびそのような型の配列を持つパラメータおよび戻り値に適用されます。テストマスクは、llvm.is.fpclassの2番目の引数と同じ形式を持ち、値に許可されない浮動小数点値のクラスを示します。たとえば、3のビットマスクは、パラメータが NaN であってはならないことを示します。

値が nofpclass テストマスクで示される浮動小数点クラスである場合、代わりに ポイズン値 が渡されるか、返されます。

リスト 19 次の不変条件が保持されます
     @llvm.is.fpclass(nofpclass(test_mask) %x, test_mask) => false
     @llvm.is.fpclass(nofpclass(test_mask) %x, ~test_mask) => true
     nofpclass(all) => poison

テキストIRでは、可読性のためにさまざまな文字列名がサポートされており、組み合わせることができます。たとえば、nofpclass(nan pinf nzero) は 547 のマスクに評価されます。

これは浮動小数点環境に依存しません。たとえば、nofpclass(zero) とマークされた関数パラメータは、ゼロ入力がないことを示します。これが、入力の非正規化数をゼロとして扱うことを示す "denormal-fp-math" でマークされた関数内の引数に適用された場合、値が0に等しい比較になる非正規化数であってはならないことを意味するわけではありません。

表 1 認識されるテストマスク名

名前

浮動小数点クラス

ビットマスク値

nan

任意の NaN

3

inf

+/- 無限大

516

norm

+/- 正規数

264

sub

+/- 非正規数

144

zero

+/- 0

96

すべてのゼロ

all

1023

snan

シグナリング NaN

1

qnan

クワイエット NaN

2

ninf

負の無限大

4

nnorm

負の正規数

8

nsub

負の非正規数

16

nzero

負のゼロ

32

pzero

正のゼロ

64

psub

正の非正規数

128

pnorm

正の正規数

256

pinf

正の無限大

512

alignstack(<n>)

これは、呼び出し規約の低減中にこのパラメータをスタックスロットに割り当てる際に、バックエンドが考慮する必要があるアライメントを示します。指定されたアライメントの強制はターゲット依存であり、ターゲット固有の呼び出し規約ルールがこの値を上書きする場合があります。この属性は、バックエンドの基本型にマッピングされない言語固有のアライメント情報を伝達する目的を果たします(たとえば、言語属性による過剰なアライメント指定)。

allocalign

この属性でマークされた関数パラメータは、この関数によって返される新しく割り当てられたブロックのバイト単位のアライメントです。返される値は、指定されたアライメントを持っているか、ヌルポインタである必要があります。返される値は、要求されたアライメントよりもアライメントされている可能性がありますが、アライメントが低くなることはありません。無効な(たとえば、2のべき乗でない)アライメントは、返されるポインタがヌルである限り、allocalign パラメータで許可されます。この属性は、整数パラメータにのみ適用できます。

allocptr

この属性でマークされた関数パラメータは、アロケータによって操作されるポインタです。realloc のような関数の場合、ポインタは成功すると無効になります(ただし、同じアドレスが返される場合があります)。free のような関数の場合、ポインタは常に無効になります。

readnone

この属性は、関数がポインタ引数を間接参照しないことを示します。ただし、他のポインタを介してアクセスした場合、ポインタが指すメモリを読み書きする可能性があります。

関数が readnone ポインタ引数から読み取りまたは書き込みを行う場合、動作は未定義です。

readonly

この属性は、関数がこのポインタ引数を通して書き込みを行わないことを示します。ただし、ポインタが指すメモリに書き込む可能性があります。

関数が readonly ポインタ引数に書き込みを行う場合、動作は未定義です。

writeonly

この属性は、関数がこのポインタ引数に書き込みを行う可能性があるが、読み取りを行わないことを示します(ただし、ポインタが指すメモリから読み取る可能性があります)。

この属性は、memory(write) 属性と同じように理解されます。つまり、関数外で読み取りが観察可能でない限り、ポインタは読み取ることができます。正確なセマンティクスについては、memory ドキュメントを参照してください。

writable

この属性は、dereferenceable(N) またはポインタ引数の最初の N バイトが間接参照可能であることを意味する別の属性と組み合わせてのみ意味があります。

その場合、この属性は、最初の N バイトが(アトミックではない方法で)ロードされ、関数のエントリ時に格納されることを示します。

これは、トラップやデータ競合を発生させることなく、関数のエントリ時にスプリアスストアを導入できることを意味します。ポインタが関数の実行中に別のスレッドにエスケープする可能性があるため、これは関数全体で必ずしも保持されるわけではありません。アトミック最適化ガイドも参照してください

間接参照可能性を意味する「その他の属性」は、dereferenceable_or_null(ポインタが非ヌルの場合)と、sretbyvalbyrefinallocapreallocated ファミリの属性です。たとえば、byval 引数は、この属性がなくても書き込み可能であることがわかっているため、これらの組み合わせのすべてが有用であるとは限りません。

writable 属性は、readnonereadonly、または argmem: write を含まない memory 属性と組み合わせることはできません。

initializes((Lo1, Hi1), ...)

この属性は、関数がポインタパラメータのメモリの範囲 [%p+LoN, %p+HiN) を初期化することを示します。メモリの初期化とは、最初のメモリアクセスが非揮発性、非アトミックな書き込みであることを意味します。書き込みは関数が戻る前に発生する必要があります。関数がアンワインドする場合、書き込みは発生しない場合があります。

この属性は、このポインタパラメータを介してアクセスされたメモリに対してのみ保持されます。他のポインタを介した同じメモリへのその他の任意アクセスは許可されます。

writable または dereferenceable 属性は、initializes 属性を意味しません。initializes 属性は、initializes が書き込み後にポインタから読み取ることを許可するため、writeonly を意味しません。

この属性は、重複または連続するリスト要素がない、昇順の定数範囲のリストです。LoN/HiN は64ビット整数であり、引数が割り当ての一部を指している場合は負の値が許可されます。空のリストは許可されていません。

dead_on_unwind

高レベルでは、この属性は、呼び出しがアンワインドした場合、ポインタ引数がデッドであることを示します。つまり、呼び出し元はメモリの内容に依存しません。アンワインドパスでのみ表示されるストアは削除できます。

より正確には、関数の実行中にポインタを介して書き込まれたメモリは、アンワインド時にポイズン値で上書きされたかのように動作します。これには、writable 属性によって暗示される暗黙的な書き込みによって書き込まれたメモリが含まれます。呼び出し元は影響を受けるメモリにアクセスできますが、ストアが先行しないすべてのロードはポイズンを返します。

この属性は戻り値に適用できません。

range(<ty> <a>, <b>)

この属性は、パラメータまたは戻り値が取りうる範囲を表現します。値が指定された範囲内にない場合、それは poison に変換されます。range に渡される引数は、以下のプロパティを持ちます。

  • 型は、パラメータまたは戻り値のスカラー型と一致する必要があります。

  • ペア a,b は、範囲 [a,b) を表します。

  • ab は両方とも定数です。

  • 範囲はラップすることが許可されています。

  • 空の範囲は 0,0 を使用して表されます。

  • それ以外の場合、ab は等しくなることは許可されていません。

この属性は、整数型または整数型のベクターを持つパラメータまたは戻り値にのみ適用できます。

ベクター型のパラメータの場合、範囲は要素ごとに適用されます。

ガベージコレクタ戦略名

各関数は、ガベージコレクタ戦略名を指定できます。これは単なる文字列です。

define void @f() gc "name" { ... }

name のサポートされている値には、LLVM に組み込まれているものと、ロードされたプラグインによって提供されるものが含まれます。GC戦略を指定すると、コンパイラは、指定されたガベージコレクションアルゴリズムをサポートするために出力を変更します。LLVM自体にはガベージコレクタが含まれていないことに注意してください。この機能は、外部から提供されたコレクタと相互運用できるマシンコードを生成することに限定されています。

プレフィックスデータ

プレフィックスデータとは、コードジェネレーターが関数のエントリポイントの直前に出力する関数に関連付けられたデータです。この機能の目的は、フロントエンドが言語固有のランタイムメタデータを特定の関数に関連付け、関数ポインタを介して利用できるようにし、なおかつ関数ポインタを呼び出せるようにすることです。

特定の関数のデータにアクセスするには、プログラムは関数ポインタを定数の型へのポインタにビットキャストし、インデックス -1 をデリファレンスできます。これは、IRシンボルがプレフィックスデータの末尾のすぐ先を指していることを意味します。たとえば、単一の i32 で注釈が付けられた関数の例を見てみましょう。

define void @f() prefix i32 123 { ... }

プレフィックスデータは、次のように参照できます。

%a = getelementptr inbounds i32, ptr @f, i32 -1
%b = load i32, ptr %a

プレフィックスデータは、プレフィックスデータの型のグローバル変数の初期化子であるかのようにレイアウトされます。関数は、プレフィックスデータの先頭がアラインされるように配置されます。これは、プレフィックスデータのサイズがアラインメントサイズの倍数でない場合、関数のエントリポイントがアラインされないことを意味します。関数のエントリポイントのアラインメントが必要な場合は、プレフィックスデータにパディングを追加する必要があります。

関数にはプレフィックスデータがあるが、本体がない場合があります。これは、最適化ツールで使用できるが、オブジェクトファイルには出力されないという点で、available_externally リンケージと同様のセマンティクスを持ちます。

プロローグデータ

prologue 属性を使用すると、関数本体の前に任意のコード(バイトとしてエンコード)を挿入できます。これは、関数のホットパッチとインストルメンテーションを有効にするために使用できます。

通常の関数呼び出しのセマンティクスを維持するには、プロローグデータに特定の形式が必要です。具体的には、モジュールのターゲットに対して有効であり、他の可視的なアクションを実行することなく、プロローグデータの直後のポイントに制御を転送する一連のマシン命令にデコードされるバイトシーケンスで開始する必要があります。これにより、インライナーやその他のパスは、プロローグデータについて推論する必要なく、関数定義のセマンティクスについて推論できます。明らかに、これにより、プロローグデータの形式はターゲットに大きく依存します。

x86アーキテクチャの有効なプロローグデータの簡単な例は i8 144 で、これは nop 命令をエンコードします。

define void @f() prologue i8 144 { ... }

一般に、プロローグデータは、メタデータをスキップする相対ブランチ命令をエンコードすることによって形成できます。これは、x86_64アーキテクチャの有効なプロローグデータの例であり、最初の2バイトは jmp .+10 をエンコードします。

%0 = type <{ i8, i8, ptr }>

define void @f() prologue %0 <{ i8 235, i8 8, ptr @md}> { ... }

関数にはプロローグデータがあるが、本体がない場合があります。これは、最適化ツールで使用できるが、オブジェクトファイルには出力されないという点で、available_externally リンケージと同様のセマンティクスを持ちます。

パーソナリティ関数

personality 属性を使用すると、関数は例外処理に使用する関数を指定できます。

属性グループ

属性グループとは、IR内のオブジェクトによって参照される属性のグループのことです。多くの関数が同じ属性セットを使用するため、.ll ファイルを読みやすくするために重要です。単一の .c ファイルに対応する .ll ファイルの退化的なケースでは、単一の属性グループが、そのファイルのビルドに使用された重要なコマンドラインフラグをキャプチャします。

属性グループはモジュールレベルのオブジェクトです。属性グループを使用するには、オブジェクトは属性グループのID(たとえば、#37)を参照します。オブジェクトは複数の属性グループを参照できます。その場合、異なるグループからの属性がマージされます。

常にインライン化されるべき関数、スタックアラインメントが4で、SSE命令を使用すべきでない関数の属性グループの例を次に示します。

; Target-independent attributes:
attributes #0 = { alwaysinline alignstack=4 }

; Target-dependent attributes:
attributes #1 = { "no-sse" }

; Function @f has attributes: alwaysinline, alignstack=4, and "no-sse".
define void @f() #0 #1 { ... }

関数属性

関数属性は、関数に関する追加情報を伝達するために設定されます。関数属性は、関数型ではなく、関数の一部と見なされるため、異なる関数属性を持つ関数は、同じ関数型を持つことができます。

関数属性は、指定された型の後に続く単純なキーワードです。複数の属性が必要な場合は、スペースで区切られます。例:

define void @f() noinline { ... }
define void @f() alwaysinline { ... }
define void @f() alwaysinline optsize { ... }
define void @f() optsize { ... }
alignstack(<n>)

この属性は、プロローグとエピローグを出力するときに、バックエンドがスタックポインタを強制的にアラインする必要があることを示します。目的のアラインメントを、2のべき乗である必要がある括弧内に指定します。

"alloc-family"="FAMILY"

これは、アロケータ関数がどの「ファミリ」に属するかを示します。競合を避けるために、ファミリ名はプライマリアロケータ関数のマングル名と一致する必要があります。つまり、malloc/calloc/realloc/freeの場合は「malloc」、::operator::new および ::operator::delete の場合は「_Znwm」、アラインされた ::operator::new および ::operator::delete の場合は「_ZnwmSt11align_val_t」です。ファミリ内のmalloc/realloc/free呼び出しのマッチングは最適化できますが、一致しない呼び出しはそのままにされます。

allockind("KIND")

アロケーション関数の動作について説明します。KIND文字列には、以下のオプションからのコンマ区切りのエントリが含まれます。

  • 「alloc」:関数は新しいメモリブロックまたはnullを返します。

  • 「realloc」:関数は新しいメモリブロックまたはnullを返します。結果がnullでない場合、ブロックの先頭から元の割り当てサイズと新しい割り当てサイズの小さい方までのメモリの内容は、allocptr 引数の内容と一致し、関数が同じアドレスを返した場合でも、allocptr 引数は無効になります。

  • 「free」:関数は、allocptr で指定されたメモリブロックを解放します。「free」のallockind としてマークされた関数はvoidを返す必要があります。

  • 「uninitialized」:新しく割り当てられたメモリ(「alloc」関数からの新しいブロック、または「realloc」関数からの拡張された容量)は初期化されません。

  • 「zeroed」:新しく割り当てられたメモリ(「alloc」関数からの新しいブロック、または「realloc」関数からの拡張された容量)はゼロにされます。

  • 「aligned」:関数は、allocalign パラメータに従ってアラインされたメモリを返します。

最初の3つのオプションは相互に排他的であり、残りのオプションは関数の動作の詳細を説明します。残りのオプションは「free」タイプの関数では無効です。

allocsize(<EltSizeParam>[, <NumEltsParam>])

この属性は、注釈付きの関数が常に少なくとも指定されたバイト数(またはnull)を返すことを示します。その引数は0から始まるパラメータ番号です。1つの引数が提供された場合、少なくとも CallSite.Args[EltSizeParam] バイトが返されたポインタで使用可能であると想定されます。2つが提供された場合、CallSite.Args[EltSizeParam] * CallSite.Args[NumEltsParam] バイトが使用可能であると想定されます。参照されるパラメータは整数型である必要があります。返されたメモリブロックの内容については、何も想定されていません。

alwaysinline

この属性は、インライナーが可能な場合は常にこの関数を呼び出し元にインライン化しようとし、この呼び出し元のアクティブなインライン化サイズしきい値を無視する必要があることを示します。

builtin

これは、関数宣言が nobuiltin 属性を使用している場合でも、コールサイトの被呼び出し関数が組み込み関数として認識される必要があることを示します。これは、nobuiltin 属性で宣言された関数への直接呼び出しのコールサイトでのみ有効です。

cold

この属性は、この関数がまれにしか呼び出されないことを示します。エッジの重みを計算する場合、コールド関数呼び出しによってポスト支配される基本ブロックもコールドと見なされます。したがって、重みは小さくなります。

convergent

この属性は、この関数が収束性があることを示します。呼び出し/起動時に表示される場合、convergent 属性は、呼び出しを収束性のある関数を呼び出しているかのように扱う必要があることを示します。これは、間接呼び出しで特に役立ちます。これがないと、そのような呼び出しをターゲットが収束性がないかのように扱う場合があります。

詳細については、収束演算のセマンティクスを参照してください。

この属性を持たない関数から llvm.experimental.convergence.entry を呼び出すとエラーになります。

disable_sanitizer_instrumentation

サニタイザーでコードをインストルメントする場合、特定の関数をスキップして、インストルメンテーションが適用されないようにすることが重要になる場合があります。

この属性は、sanitize_<name> 属性がない場合と常に同じではありません。特定のサニタイザーによっては、誤検知の報告を防ぐために、sanitize_<name> 属性に関係なく、コードを関数に挿入できます。

disable_sanitizer_instrumentation は、sanitize_<name> 属性やその他のコンパイラフラグよりも優先され、あらゆる種類のインストルメンテーションを無効にします。

"dontcall-error"

この属性は、この属性を持つ関数の呼び出しが最適化によって削除されなかった場合に、エラー診断を発行する必要があることを示します。フロントエンドは、このような被呼関数の呼び出し箇所にオプションのsrclocメタデータノードを提供して、ソース言語のどこからそのような呼び出しが発生したかに関する情報を付加できます。文字列値を注釈として提供できます。

"dontcall-warn"

この属性は、この属性を持つ関数の呼び出しが最適化によって削除されなかった場合に、警告診断を発行する必要があることを示します。フロントエンドは、このような被呼関数の呼び出し箇所にオプションのsrclocメタデータノードを提供して、ソース言語のどこからそのような呼び出しが発生したかに関する情報を付加できます。文字列値を注釈として提供できます。

fn_ret_thunk_extern

この属性は、関数の戻り値を外部で定義されたアーキテクチャ固有のシンボルへのジャンプに置き換える必要があることをコードジェネレーターに伝えます。X86の場合、このシンボルの識別子は__x86_return_thunkです。

"frame-pointer"

この属性は、関数がフレームポインタを保持するかどうかをコードジェネレーターに伝えます。この属性でフレームポインタを削除できるとされていても、コードジェネレーターはフレームポインタを発行する場合があります。許容される文字列値は次のとおりです。

  • "none" (デフォルト) - フレームポインタを削除でき、そのレジスタを他の目的で使用できます。

  • "reserved" - フレームポインタレジスタは、現在の関数の有効なフレームレコードを指すように更新するか、変更しない必要があります。

  • "non-leaf" - 関数が他の関数を呼び出す場合は、フレームポインタを保持する必要があります。

  • "all" - フレームポインタを保持する必要があります。

hot

この属性は、この関数がプログラム実行のホットスポットであることを示します。関数はより積極的に最適化され、局所性を改善するためにテキストセクションの特別なサブセクションに配置されます。

プロファイルフィードバックが有効になっている場合、この属性はプロファイル情報よりも優先されます。関数をhotとマークすることにより、ユーザーはトレーニング入力がすべてのホット関数を適切にカバーしていない場合に対応できます。

inlinehint

この属性は、ソースコードにこの関数をインライン化することが望ましいというヒントが含まれていることを示します(C/C++の「inline」キーワードなど)。これは単なるヒントであり、インライナーに要求を課すものではありません。

jumptable

この属性は、関数をコード生成時にジャンプ命令テーブルに追加する必要があり、この関数へのすべてのアドレス取得参照を、適切なジャンプ命令テーブルの関数ポインターへの参照に置き換える必要があることを示します。これにより、元の関数の新しいポインターが作成されるため、関数ポインターの同一性に依存するコードが壊れる可能性があることに注意してください。したがって、jumptableで注釈が付けられた関数は、unnamed_addrでもある必要があります。

memory(...)

この属性は、呼び出し箇所または関数の可能なメモリ効果を指定します。可能なメモリロケーションの種類(argmeminaccessiblemem、およびデフォルト)に対して、可能なアクセス種類(nonereadwrite、またはreadwrite)を指定できます。例を挙げると理解しやすくなります。

  • memory(none):メモリにアクセスしません。

  • memory(read):任意のメモリを読み取る可能性があります(書き込みはしません)。

  • memory(write):任意のメモリを書き込む可能性があります(読み取りはしません)。

  • memory(readwrite):任意のメモリを読み書きする可能性があります。

  • memory(argmem: read):引数メモリのみを読み取る可能性があります。

  • memory(argmem: read, inaccessiblemem: write):引数メモリのみを読み取り、アクセスできないメモリのみを書き込む可能性があります。

  • memory(read, argmem: readwrite):任意のメモリ(デフォルトモード)を読み取り、さらに引数メモリを書き込む可能性があります。

  • memory(readwrite, argmem: none):引数メモリを除く任意のメモリにアクセスできます。

サポートされているアクセス種類は次のとおりです。

  • readwrite:ロケーションへのあらゆる種類のアクセスが許可されます。

  • read:ロケーションは読み取り専用です。ロケーションへの書き込みは、直ちに未定義の動作になります。これには、ロケーションから読み取ってから同じ値を書き戻す場合も含まれます。

  • write:ロケーションへの書き込みのみが関数呼び出しの外部で観測可能です。ただし、関数は書き込み後に内部でロケーションを読み取る可能性があります。これは観測できないためです。書き込み前にロケーションを読み取ると、poison値になります。

  • none:ロケーションへの読み取りまたは書き込みは、関数の外部では観測されません。memory(none)が使用されている場合でも、allocaの読み取りと書き込み、およびグローバル定数の読み取りは常に有効です。これらの影響は外部から観測できないためです。

サポートされているメモリロケーションの種類は次のとおりです。

  • argmem:これは、関数へのポインター引数に基づくアクセスを指します。

  • inaccessiblemem:これは、現在のモジュールがアクセスできないメモリへのアクセスを指します(関数からの戻り前。アロケーター関数は、アクセスできないメモリ自体にのみアクセスしながら、新しくアクセス可能なメモリを返す場合があります)。アクセスできないメモリは、多くの場合、組み込み関数の制御依存関係をモデル化するために使用されます。

  • デフォルトのアクセス種類(ロケーションプレフィックスなしで指定)は、明示的に指定されていないすべてのロケーション(グローバルまたはキャプチャされたポインターへのアクセスなど、現在専用のロケーション種類を持たないものを含む)に適用されます。

memory属性が指定されていない場合、memory(readwrite)が暗黙的に指定されます(すべてのメモリ効果が可能です)。

呼び出しのメモリ効果は、CallSiteEffects & (FunctionEffects | OperandBundleEffects)として計算できます。したがって、呼び出し箇所のアノテーションは、関数アノテーションまたはオペランドバンドルによって記述された潜在的な効果よりも優先されます。

minsize

この属性は、最適化パスとコードジェネレーターパスで、この関数のコードサイズを可能な限り小さく保ち、生成されたコードのサイズを最小限に抑えるために、実行時パフォーマンスを犠牲にする可能性のある最適化を行うことを示唆します。この属性は、optdebug属性およびoptnone属性と互換性がありません。

naked

この属性は、関数のプロローグ/エピローグの発行を無効にします。これは、システム固有の結果をもたらす可能性があります。naked関数の引数は、IR値を通して参照できません。

"no-inline-line-tables"

この属性がtrueに設定されている場合、インライナーはコードをインライン化するときにソースロケーションを破棄し、代わりに呼び出し箇所のソースロケーションを使用します。現在の関数にインライン化されたコードに設定されたブレークポイントは、インライン化された呼び出し箇所の実行中に発生しません。デバッガーがインライン化された呼び出し箇所の内部で停止した場合、最も外側のインライン化された呼び出し箇所で停止したように見えます。

no-jump-tables

この属性がtrueに設定されている場合、switch caseの縮小から生成できるジャンプテーブルとルックアップテーブルは無効になります。

nobuiltin

これは、呼び出し箇所での被呼関数が組み込み関数として認識されないことを示します。LLVMは、呼び出し箇所がbuiltin属性を使用している場合を除き、元の呼び出しを保持し、組み込み関数のセマンティクスに基づいて同等のコードに置き換えません。これは、呼び出し箇所と関数の宣言および定義で有効です。

nocallback

この属性は、関数が戻り値または例外によってのみ呼び出し元のモジュールにジャンプすることが許可されており、コールバック関数、直接的または推移的な外部関数呼び出し、longjmpの使用、またはその他の手段でジャンプバックすることが許可されていないことを示します。これは、データフロー分析を改善するためにモジュールレベルで使用されるコンパイラヒントであり、リンク中に削除され、現在のモジュールで定義された関数には影響しません。

noduplicate

この属性は、関数への呼び出しを複製できないことを示します。noduplicate関数への呼び出しは、親関数内で移動できますが、親関数内で複製することはできません。

noduplicate呼び出しを含む関数は、インライン化によって呼び出しが複製されない場合、インライン化の候補になる可能性があります。これは、関数が内部リンケージを持ち、呼び出し箇所が1つしかないことを意味するため、インライン化後、元の呼び出しは不要になります。

nofree

この関数属性は、関数が、直接的または推移的に、呼び出し前に存在していたメモリアロケーションに対するメモリ割り当て解除関数(例:free)を呼び出さないことを示します。

その結果、nofree属性を持つ関数への呼び出し前に逆参照可能であることがわかっているキャプチャされていないポインターは、呼び出し後も逆参照可能であることがわかります。キャプチャ条件は、関数がポインターを別のスレッドに通信し、そのスレッドがメモリを割り当て解除する可能性がある環境で必要です。または、nosyncは、そのような通信が発生しないことを保証し、キャプチャされたポインターでさえ関数によって解放できないことを保証します。

nofree関数は、割り当てたメモリを解放すること、または(nosyncでない場合)別のスレッドに代わってメモリを解放するように手配することを明示的に許可されています。その結果、驚くべきことに、nofree関数は、以前に割り当て解除されたメモリオブジェクトへのポインターを返すことができます。

noimplicitfloat

暗黙的な浮動小数点コードを許可しません。これにより、浮動小数点コードと浮動小数点レジスタを名目上浮動小数点ではない操作に使用する最適化が抑制されます。浮動小数点演算を実行するか、浮動小数点レジスタへのアクセスを必要とするLLVM命令は、引き続き浮動小数点コードを生成する可能性があります。

また、ベクトル化やmemcpy/memset最適化など、スカラーコードからSIMD/ベクトルコードとレジスタを作成する最適化も抑制します。これには、整数ベクトルが含まれます。IRに存在するベクトル命令は、引き続きベクトルコードを生成する可能性があります。

noinline

この属性は、インライナーがいかなる状況でもこの関数をインライン化しない必要があることを示します。この属性は、alwaysinline属性と一緒に使用することはできません。

nomerge

この属性は、この関数への呼び出しを最適化中にマージしない必要があることを示します。たとえば、例外を発生させるか、プログラムを終了させる、それ以外は同一のコードシーケンスの末尾のマージを防止します。通常、末尾のマージはソースロケーション情報の精度を低下させ、スタックトレースがデバッグに役に立たなくなります。この属性を使用すると、ユーザーはコードサイズとデバッグ情報の精度のトレードオフを制御できます。

nonlazybind

この属性は、関数の遅延シンボルバインディングを抑制します。これにより、プログラムの起動時に関数が呼び出されない場合、プログラムの起動時間が余分にかかる代わりに、関数呼び出しが高速になる可能性があります。

noprofile

この関数属性は、カバレッジやプロファイルベースの最適化に使用される、インストルメンテーションベースのプロファイリングが関数に追加されるのを防ぎます。また、呼び出し元と呼び出し先のこの属性の値が異なる場合、インライン化をブロックします。

skipprofile

この関数属性は、カバレッジやプロファイルベースの最適化に使用される、インストルメンテーションベースのプロファイリングが関数に追加されるのを防ぎます。この属性はインライン化を制限しないため、インストルメントされた命令がこの関数に組み込まれる可能性があります。

noredzone

この属性は、ターゲット固有のABIで通常許可されている場合でも、コードジェネレーターがレッドゾーンを使用しないように指示します。

indirect-tls-seg-refs

この属性は、ターゲット固有のABIで通常許可されている場合でも、コードジェネレーターがセグメントレジスタを介した直接TLSアクセスを使用しないように指示します。

noreturn

この関数属性は、関数が return 命令を通して正常に返らないことを示します。関数が動的に return する場合、これは実行時に未定義の動作を引き起こします。注釈付き関数は例外を発生させる可能性があり、つまり、nounwind は暗黙的に含まれません。

norecurse

この関数属性は、関数が直接的または間接的に可能な呼び出しパスで自身を呼び出さないことを示します。関数が再帰する場合、これは実行時に未定義の動作を引き起こします。

willreturn

この関数属性は、この関数の呼び出しが未定義の動作を示すか、現在の呼び出しを含む既存のコールスタック内のポイントに戻って実行を継続することを示します。注釈付き関数は例外を発生させる可能性があり、つまり、nounwind は暗黙的に含まれません。注釈付き関数の呼び出しがコールスタック内のポイントに制御を返さない場合、動作は未定義です。

nosync

この関数属性は、関数がメモリやその他の明確に定義された手段を介して別のスレッドと通信(同期)しないことを示します。同期は、順序を強制するatomicアクセス(したがって「unordered」および「monotonic」ではない)、volatileアクセス、およびconvergent関数の呼び出しの存在下で可能と見なされます。

convergent操作は、メモリを介さないと見なされる通信を含み、メモリモデルの目的でスレッド間の順序を必ずしも暗示しないことに注意してください。したがって、操作はconvergentnosyncの両方である可能性があります。

nosync関数が別のスレッドと同期する場合、動作は未定義です。

nounwind

この関数属性は、関数が例外を発生させないことを示します。関数が例外を発生させた場合、そのランタイム動作は未定義です。ただし、nounwindとマークされた関数は、トラップまたは非同期例外を生成する可能性があります。LLVMによって非同期例外を処理することが認識されている例外処理スキーム(SEHなど)は、実装定義されたセマンティクスを依然として提供します。

nosanitize_bounds

この属性は、この関数に対して境界チェックサニタイザーのインストルメンテーションが無効になっていることを示します。

nosanitize_coverage

この属性は、この関数に対して SanitizerCoverage インストルメンテーションが無効になっていることを示します。

null_pointer_is_valid

null_pointer_is_valid が設定されている場合、アドレス空間0の null アドレスは、メモリのロードとストアに対して有効なアドレスと見なされます。分析または最適化では、この関数で null へのポインターの逆参照を未定義の動作として扱わない必要があります。注: グローバル変数のアドレスと null を比較すると、定数式内でこの属性を照会する制限があるため、false と評価される可能性があります。

optdebug

この属性は、最適化パスとコードジェネレーターパスが、ランタイムパフォーマンスを大幅に低下させることなくデバッグ情報を保持しようとする選択を行うことを示唆します。この属性は、minsizeoptsize、およびoptnone属性と互換性がありません。

optforfuzzing

この属性は、この関数が最大ファジングシグナルに対して最適化される必要があることを示します。

optnone

この関数属性は、ほとんどの最適化パスがこの関数をスキップすることを示します。ただし、プロシージャ間最適化パスは例外です。コード生成は、デフォルトで「高速」命令セレクターを使用します。この属性は、alwaysinline 属性と一緒に使用することはできません。この属性は、minsizeoptsize、およびoptdebug属性とも互換性がありません。

この属性では、関数にnoinline属性も指定する必要があるため、関数は呼び出し元にインライン化されることはありません。alwaysinline属性を持つ関数のみが、この関数の本体へのインライン化の有効な候補です。

optsize

この属性は、最適化パスとコードジェネレーターパスが、この関数のコードサイズを低く抑える選択を行い、それ以外の場合はランタイムパフォーマンスに大きな影響を与えない限り、コードサイズを削減するために特に最適化を行うことを示唆します。この属性は、optdebugおよびoptnone属性と互換性がありません。

"patchable-function"

この属性は、ランタイム関数が後で上書きできるように、この関数用に生成されたコードが特定の規則に従う必要があることをコードジェネレーターに伝えます。この属性の正確な効果は、その文字列値によって異なり、現在有効な可能性は1つです。

  • "prologue-short-redirect" - このスタイルのパッチ可能な関数は、スレッドセーフな方法で関数から制御をリダイレクトするために、関数プロローグをパッチすることをサポートするように設計されています。関数の最初の命令が短いジャンプ命令を収容するのに十分な大きさであり、アトミックなcompare-and-swap命令で完全に変更できるのに十分な配置であることを保証します。最初の要件は、十分な大きさのNOPを挿入することで満たすことができますが、LLVMは、短いジャンプよりも大きいパッチ可能な命令として既存の命令(つまり、とにかく出力する必要がある命令)を再利用しようとすることができます。

    "prologue-short-redirect" は、現在 x86-64 でのみサポートされています。

この属性自体は、プロシージャ間最適化に制限を課すものではありません。パッチが持つ可能性のある意味的な影響はすべて、リンケージタイプを介して個別に伝える必要があります。

"probe-stack"

この属性は、関数がスタックの最後にガード領域をトリガーすることを示します。これにより、スタックへのアクセスは、スタックへの以前のアクセスに対するガード領域のサイズを超えてはならないことが保証されます。これには、呼び出されるスタックプロービング関数の名前である、1つの必須の文字列値が必要です。

"probe-stack"属性を持つ関数が、別の"probe-stack"属性を持つ関数にインライン化される場合、結果の関数には呼び出し元の"probe-stack"属性があります。"probe-stack"属性を持つ関数が、"probe-stack"属性をまったく持たない関数にインライン化される場合、結果の関数には呼び出し先の"probe-stack"属性があります。

"stack-probe-size"

この属性は、スタックプローブの動作を制御します。"probe-stack"属性、またはABIで必要なスタックプローブ(存在する場合)のいずれかです。これは、ガード領域のサイズを定義します。関数がガード領域のサイズよりも多くのスタック空間を使用する可能性がある場合、スタックプロービングシーケンスが出力されることを保証します。これには、デフォルトで4096である1つの必須整数値が必要です。

"stack-probe-size"属性を持つ関数が、別の"stack-probe-size"属性を持つ関数にインライン化される場合、結果の関数には数値の小さい方の"stack-probe-size"属性があります。"stack-probe-size"属性を持つ関数が、"stack-probe-size"属性をまったく持たない関数にインライン化される場合、結果の関数には呼び出し先の"stack-probe-size"属性があります。

"no-stack-arg-probe"

この属性は、ABIで必要なスタックプローブ(存在する場合)を無効にします。

returns_twice

この属性は、この関数が2回 return できることを示します。Cのsetjmpはそのような関数の例です。コンパイラは、これらの関数の呼び出し元で一部の最適化(末尾呼び出しなど)を無効にします。

safestack

この属性は、この関数でSafeStack保護が有効になっていることを示します。

safestack属性を持つ関数が、safestack属性を持たない、またはsspsspstrong、またはsspreq属性を持つ関数にインライン化される場合、結果の関数はsafestack属性を持ちます。

sanitize_address

この属性は、AddressSanitizerチェック(動的なアドレス安全性分析)がこの関数で有効になっていることを示します。

sanitize_memory

この属性は、MemorySanitizerチェック(初期化されていないメモリへのアクセスの動的な検出)がこの関数で有効になっていることを示します。

sanitize_thread

この属性は、ThreadSanitizerチェック(動的なスレッド安全性分析)がこの関数で有効になっていることを示します。

sanitize_hwaddress

この属性は、HWAddressSanitizerチェック(タグ付きポインターに基づく動的なアドレス安全性分析)がこの関数で有効になっていることを示します。

sanitize_memtag

この属性は、MemTagSanitizerチェック(Armv8 MTEに基づく動的なアドレス安全性分析)がこの関数で有効になっていることを示します。

sanitize_realtime

この属性は、RealtimeSanitizerチェック(リアルタイム安全性分析 - 割り当て、システムコール、例外なし)がこの関数で有効になっていることを示します。

speculative_load_hardening

この属性は、関数本体でSpeculative Load Hardeningを有効にする必要があることを示します。

Speculative Load Hardeningは、制御フローミススペキュレーション、特に分岐が実行されるかどうかに関するミススペキュレーションを利用する情報漏洩攻撃に対する最善の努力による軽減策です。通常、このような攻撃を可能にする脆弱性は「Spectre variant #1」として分類されます。特に、これは「Spectre variant #2」脆弱性として分類される、分岐ターゲットのミススペキュレーションに対する軽減を試みるものではありません。

インライン化する場合、この属性は固定されます。この属性を持つ関数をインライン化すると、呼び出し元もこの属性を持つようになります。これは、この属性で注釈された関数内のコードが、常に(インライン化後でも)強化されるという、最大限に保守的なモデルを提供することを目的としています。

speculatable

この関数属性は、関数が結果を計算する以外の副作用を持たず、未定義の動作がないことを示します。ただし、speculatable 属性だけでは、特定の実行パスにおいて、この関数への呼び出し回数が外部から観測可能でないとは結論付けられないことに注意してください。この属性は、個々の呼び出しサイトではなく、関数および宣言に対してのみ有効です。関数が誤って speculatable とマークされ、実際には未定義の動作を示す場合、呼び出しサイトがデッドコードであっても、未定義の動作が観測される可能性があります。

ssp

この属性は、関数がスタック破壊プロテクターを生成する必要があることを示します。これは「カナリア」の形式であり、ローカル変数の前にスタックに配置されたランダムな値で、関数からの戻り時に上書きされていないかを確認します。関数がスタックプロテクターを必要とするかどうかを判断するためにヒューリスティックが使用されます。使用されるヒューリスティックは、以下の関数に対してプロテクターを有効にします。

  • ssp-buffer-size(デフォルトは 8)よりも大きい文字配列。

  • ssp-buffer-sizeよりも大きい文字配列を含む集約体。

  • 可変サイズまたはssp-buffer-sizeよりも大きい定数サイズを持つ alloca() の呼び出し。

プロテクターが必要と識別された変数は、スタックプロテクターガードに隣接するようにスタックに配置されます。

ssp 属性を持つ関数が呼び出し元の関数にインライン化された場合、この属性は呼び出し元の関数に引き継がれません。

sspstrong

この属性は、関数がスタック破壊プロテクターを生成する必要があることを示します。この属性により、関数がスタックプロテクターを必要とするかどうかを判断する際に強力なヒューリスティックが使用されます。強力なヒューリスティックは、以下の関数に対してプロテクターを有効にします。

  • 任意のサイズと型の配列

  • 任意のサイズと型の配列を含む集約体。

  • alloca() の呼び出し。

  • アドレスが取得されたローカル変数。

プロテクターが必要と識別された変数は、スタックプロテクターガードに隣接するようにスタックに配置されます。具体的なレイアウトルールは次のとおりです。

  1. 大きな配列と大きな配列を含む構造体(>= ssp-buffer-size)は、スタックプロテクターに最も近い場所に配置されます。

  2. 小さな配列と小さな配列を含む構造体(< ssp-buffer-size)は、プロテクターに 2 番目に近い場所に配置されます。

  3. アドレスが取得された変数は、プロテクターに 3 番目に近い場所に配置されます。

これは、ssp 関数属性をオーバーライドします。

sspstrong 属性を持つ関数が、ssp 属性を持つ呼び出し元の関数にインライン化された場合、呼び出し元の関数の属性は sspstrong にアップグレードされます。

sspreq

この属性は、関数が常にスタック破壊プロテクターを生成する必要があることを示します。これは、ssp および sspstrong 関数属性をオーバーライドします。

プロテクターが必要と識別された変数は、スタックプロテクターガードに隣接するようにスタックに配置されます。具体的なレイアウトルールは次のとおりです。

  1. 大きな配列と大きな配列を含む構造体(>= ssp-buffer-size)は、スタックプロテクターに最も近い場所に配置されます。

  2. 小さな配列と小さな配列を含む構造体(< ssp-buffer-size)は、プロテクターに 2 番目に近い場所に配置されます。

  3. アドレスが取得された変数は、プロテクターに 3 番目に近い場所に配置されます。

sspreq 属性を持つ関数が、ssp または sspstrong 属性を持つ呼び出し元の関数にインライン化された場合、呼び出し元の関数の属性は sspreq にアップグレードされます。

strictfp

この属性は、関数が厳密な浮動小数点セマンティクスを必要とするスコープから呼び出されたことを示します。LLVMは、浮動小数点丸めモードに関する仮定を必要とする、またはこの関数を呼び出すことで設定またはクリアされる可能性のある浮動小数点ステータスフラグの状態を変更する可能性のある最適化を試みません。LLVMは、トラップする可能性のある新しい浮動小数点命令を導入しません。

"denormal-fp-math"

これは、デフォルトの浮動小数点環境で想定される非正規化数(サブノーマル数)の処理を示します。これは、コンマ区切りのペアです。要素は、"ieee""preserve-sign""positive-zero"、または "dynamic" のいずれかになります。最初のエントリは、浮動小数点演算の結果のフラッシュモードを示します。2番目のエントリは、浮動小数点命令への非正規化数の入力の処理を示します。古いビットコードとの互換性のために、2番目の値が省略されている場合、入力モードと出力モードの両方が同じモードを想定します。

この属性が指定されていない場合、デフォルトは "ieee,ieee" です。

出力モードが "preserve-sign" または "positive-zero" の場合、非正規化数の出力は、標準の浮動小数点演算によってゼロにフラッシュされる可能性があります。ゼロへのフラッシュが発生することが義務付けられているわけではありませんが、非正規化数の出力がゼロにフラッシュされる場合は、符号モードを尊重する必要があります。すべてのターゲットがすべてのモードをサポートしているわけではありません。

モードが "dynamic" の場合、動作は浮動小数点環境の動的な状態から導き出されます。非正規化数の動作に依存する変換は実行しないでください。

これは、関数が実行されると予想される浮動小数点モードを示しますが、モードの一貫性を確保するための試みは行いません。ユーザーまたはプラットフォームコードは、関数のエントリ前に浮動小数点モードを適切に設定することが期待されます。

入力モードが "preserve-sign" または "positive-zero" の場合、浮動小数点演算は、入力された非正規化数をゼロとして扱う必要があります。状況によっては、命令がこのモードを尊重しない場合、正確性のために、低レベル化中に @llvm.canonicalize によって 0 に変換する必要がある場合があります。

"denormal-fp-math-f32"

"denormal-fp-math" と同じですが、32ビットfloat型(または32ビットfloatのベクトル)の動作のみを制御します。両方が存在する場合、これは "denormal-fp-math" をオーバーライドします。すべてのターゲットが型ごとに非正規化モードを個別に設定することをサポートしているわけではなく、サポートされていない使用法を診断する試みは行われません。現在、この属性は AMDGPU および NVPTX バックエンドで尊重されています。

"thunk"

この属性は、関数がテールコールで他の関数に委譲することを示します。サンクのプロトタイプは、最適化の目的で使用しないでください。呼び出し元は、サンクのプロトタイプをキャストして、サンクのターゲットプロトタイプと一致させることが期待されます。

"tls-load-hoist"

この属性は、関数が tls 変数をホイストすることにより、冗長な tls アドレス計算を削減しようとすることを示します。

uwtable[(sync|async)]

この属性は、ターゲットとする ABI が、例外が通過しないことを示すことができる場合でも、この関数に対してアンワインドテーブルエントリを生成することを要求することを示します。これは通常、ELF x86-64 abi の場合に当てはまりますが、一部のコンパイルユニットでは無効にできます。オプションのパラメーターは、生成するアンワインドテーブルの種類を記述します。通常のアンワインドテーブルの場合は sync、非同期(命令精度)アンワインドテーブルの場合は async です。パラメーターがない場合、属性 uwtableuwtable(async) と同等です。

nocf_check

この属性は、属性付きエンティティで制御フローチェックが実行されないことを示します。これにより、特定のエンティティに対して -fcf-protection=<> が無効になり、HW 制御フロー保護メカニズムが細かく調整されます。このフラグはターゲットに依存せず、現在は関数または関数ポインターに付随します。

shadowcallstack

この属性は、関数に対して ShadowCallStack チェックが有効になっていることを示します。このインストルメンテーションは、関数のプロローグとエピローグの間で関数の戻りアドレスが変更されていないことをチェックします。現在、x86_64 に固有です。

mustprogress

この属性は、関数が戻るか、アンワインドするか、または揮発性メモリアクセス、I/O、その他の同期などを介して、観測可能な方法で環境とやり取りする必要があることを示します。mustprogress 属性は、C++ 標準の [intro.progress] の最初のセクションの要件をモデル化することを目的としています。結果として、mustprogress 属性を持つ関数内のループは、観測可能な方法で環境とやり取りしない場合、終了すると想定でき、副作用のない終了ループは削除できます。mustprogress 関数がこの契約を満たさない場合、動作は未定義です。mustprogress 関数が mustprogress とマークされていない関数を呼び出し、その関数が決して戻らない場合でも、他に観測可能な進行がない場合でも、プログラムは適切に定義されます。willreturnmustprogress を暗示することに注意してください。

"warn-stack-size"="<threshold>"

この属性は、フレームサイズが指定された値を超えた場合にフレームサイズがわかると診断を出力するためのしきい値を設定します。これは、負でない整数で、UINT_MAX 未満である必要のある 1 つの必須整数値を取ります。異なる値を持つ重複する定義がリンクされている場合、どのしきい値が使用されるかは不明です。

vscale_range(<min>[, <max>])

この関数属性は、vscale が指定された範囲内の 2 のべき乗であることを示します。min は 0 より大きい 2 のべき乗である必要があります。指定した場合、maxmin 以上であるか、上限なしを示す 0 である必要があります。vscale_range(<val>) 構文を使用して、minmax の両方を同じ値に設定できます。この属性を含まない関数は、vscale の値について何も仮定しません。

"nooutline"

この属性は、アウトライン化パスが関数を変更しないようにすることを示します。

呼び出しサイト属性

関数属性に加えて、次の呼び出しサイトのみの属性がサポートされています。

vector-function-abi-variant

この属性は、関数に関連付けられたベクトル関数をリストするために、call に付与できます。この属性は、invoke 命令や callbr 命令には付与できないことに注意してください。この属性は、コンマで区切られたマングル名のリストで構成されます。リストの順序は優先度を意味するものではありません(論理的には集合です)。コンパイラは、リストされた任意のベクトル関数を自由に選択できます。

マングル名の構文は以下のとおりです。

_ZGV<isa><mask><vlen><parameters>_<scalar_name>[(<vector_redirection>)]

この属性が存在する場合、コンパイラは関数 <scalar_name> に、<scalar_name> のベクトル上での同時呼び出しを実行するために使用できる対応するベクトルバリアントがあることを通知します。ベクトル関数の形状は、接頭辞 _ZGV<scalar_name> トークンの間にあるトークンによって記述されます。ベクトル関数の標準名は _ZGV<isa><mask><vlen><parameters>_<scalar_name> です。オプションのトークン (<vector_redirection>) が存在する場合、標準名に加えてカスタム名が提供されることをコンパイラに通知します(カスタム名は、たとえば OpenMP 5.0 で declare variant を使用して提供できます)。バリアントの宣言は、IR モジュール内に存在する必要があります。ベクトルバリアントのシグネチャは、ターゲットのベクトル関数 ABI(VFABI)仕様の規則によって決定されます。Arm および X86 の場合、VFABI はそれぞれ https://github.com/ARM-software/abi-aa および https://software.intel.com/content/www/us/en/develop/download/vector-simd-function-abi.html にあります。

X86 および Arm ターゲットの場合、標準名内のトークンの値は、VFABI で定義されているものです。LLVM には、ターゲット ISA に直接関連付けられていない関数(たとえば、TargetLibraryInfo に保存されているマッピングの一部)のスカラーからベクトルへのマッピングを作成するために使用できる内部 <isa> トークンがあります。<isa> トークンの有効な値は次のとおりです。

<isa>:= b | c | d | e  -> X86 SSE, AVX, AVX2, AVX512
      | n | s          -> Armv8 Advanced SIMD, SVE
      | __LLVM__       -> Internal LLVM Vector ISA

現在サポートされているすべてのターゲット(x86、Arm、および内部 LLVM)の場合、残りのトークンは次の値を持つことができます。

<mask>:= M | N         -> mask | no mask

<vlen>:= number        -> number of lanes
       | x             -> VLA (Vector Length Agnostic)

<parameters>:= v              -> vector
             | l | l <number> -> linear
             | R | R <number> -> linear with ref modifier
             | L | L <number> -> linear with val modifier
             | U | U <number> -> linear with uval modifier
             | ls <pos>       -> runtime linear
             | Rs <pos>       -> runtime linear with ref modifier
             | Ls <pos>       -> runtime linear with val modifier
             | Us <pos>       -> runtime linear with uval modifier
             | u              -> uniform

<scalar_name>:= name of the scalar function

<vector_redirection>:= optional, custom name of the vector function
preallocated(<ty>)

この属性は、llvm.call.preallocated.arg の呼び出しで必須であり、他のどの呼び出しにも使用できません。詳細については、llvm.call.preallocated.arg を参照してください。

グローバル属性

属性は、グローバル変数に関する追加情報を伝達するために設定できます。関数属性とは異なり、グローバル変数の属性は単一の属性グループにグループ化されます。

no_sanitize_address

この属性は、グローバル変数が __attribute__((no_sanitize(“address”)))__attribute__((disable_sanitizer_instrumentation)) で注釈が付けられているか、-fsanitize-ignorelist ファイルに含まれているため、AddressSanitizer インストルメンテーションが適用されないようにする必要があることを示します。

no_sanitize_hwaddress

この属性は、グローバル変数が __attribute__((no_sanitize(“hwaddress”)))__attribute__((disable_sanitizer_instrumentation)) で注釈が付けられているか、-fsanitize-ignorelist ファイルに含まれているため、HWAddressSanitizer インストルメンテーションが適用されないようにする必要があることを示します。

sanitize_memtag

この属性は、グローバル変数に AArch64 メモリタグ(MTE)インストルメンテーションを適用する必要があることを示します。この属性により、GlobalMerge などの特定の最適化が抑制されるだけでなく、アセンブリで追加のディレクティブが発行され、リンカーがアクセスを MTE で保護できるように、オブジェクトファイルに追加のメタデータビットが配置されることが保証されます。この属性は、グローバルが __attribute__((no_sanitize(“memtag”)))__attribute__((disable_sanitizer_instrumentation)) でマークされていないか、-fsanitize-ignorelist ファイルに含まれていない限り、-fsanitize=memtag-globals が指定されている場合に clang によって追加されます。AArch64 グローバルタグ付けパスは、グローバルにタグ付けできない場合(TLS 変数など)に、この属性を削除する場合があります。

sanitize_address_dyninit

この属性は、AddressSanitizer でインストルメントされた場合、グローバル変数が ODR 違反がないかチェックする必要があることを示します。この属性は、C++ の規則に従って動的に初期化されるグローバル変数に適用されます。

オペランドバンドル

オペランドバンドルは、特定の LLVM 命令(現在は call および invoke のみ)に関連付けることができるタグ付きの SSA 値のセットです。ある意味ではメタデータのようですが、それらをドロップすることは正しくなく、プログラムのセマンティクスが変更されます。

構文

operand bundle set ::= '[' operand bundle (, operand bundle )* ']'
operand bundle ::= tag '(' [ bundle operand ] (, bundle operand )* ')'
bundle operand ::= SSA value
tag ::= string constant

オペランドバンドルは関数のシグネチャの一部ではなく、特定の関数は、異なる種類のオペランドバンドルを使用して複数の場所から呼び出すことができます。これは、オペランドバンドルが概念的には、ディスパッチされる被呼び出し側ではなく、call(または invoke)の一部であるという事実を反映しています。

オペランドバンドルは、マネージド言語のランタイムイントロスペクションのような機能をサポートするための汎用的なメカニズムです。オペランドバンドルの正確なセマンティクスはバンドルタグに依存しますが、オペランドバンドルの存在がプログラムのセマンティクスにどの程度影響するかには、特定の制限があります。これらの制限は、「不明な」オペランドバンドルのセマンティクスとして記述されます。オペランドバンドルの動作がこれらの制限内で記述可能である限り、LLVM はそれを含むプログラムを誤コンパイルしないために、オペランドバンドルに関する特別な知識を持っている必要はありません。

  • 不明なオペランドバンドルのバンドルオペランドは、制御が被呼び出し側またはインボーク側に転送される前に、不明な方法でエスケープします。

  • オペランドバンドルを持つ呼び出しおよびインボークは、呼び出しターゲットが memory 属性を指定している場合でも、エントリおよび終了時にヒープに対する不明な読み取り/書き込み効果があります。それらが呼び出しサイト固有の属性で上書きされない限りです。

  • 呼び出しサイトでのオペランドバンドルは、呼び出された関数の実装を変更できません。インタープロシージャルの最適化は、最初の 2 つのプロパティを考慮に入れる限り、通常どおりに機能します。

以下では、より具体的なタイプのオペランドバンドルについて説明します。

非最適化オペランドバンドル

非最適化オペランドバンドルは、"deopt" オペランドバンドルタグで特徴付けられます。これらのオペランドバンドルは、付与された呼び出しサイトの代替の「安全な」継続を表し、適切なランタイムによって、指定された呼び出しサイトでコンパイルされたフレームを非最適化するために使用できます。呼び出しサイトに付与できる "deopt" オペランドバンドルは最大で 1 つです。非最適化の正確な詳細は言語リファレンスの範囲外ですが、通常はコンパイルされたフレームを解釈されたフレームのセットに書き換えることが含まれます。

コンパイラの観点からは、非最適化オペランドバンドルは、それらが付与された呼び出しサイトを少なくとも readonly にします。それらは、ポインター型オペランドのすべて(それらが他の方法でエスケープされない場合でも)と、可視のヒープ全体を読み込みます。非最適化オペランドバンドルは、非最適化中を除いて、オペランドをキャプチャしません。その場合、制御はコンパイルされたフレームに戻りません。

インライナーは、非最適化オペランドバンドルを持つ呼び出しを通じてインライン化する方法を知っています。通常の呼び出しサイトを通るインライン化が通常および例外的な継続を構成することを伴うのと同様に、非最適化オペランドバンドルを持つ呼び出しサイトを通るインライン化は、適切な「安全な」非最適化継続を構成する必要があります。インライナーは、インライン化された本体のすべての非最適化継続に親の非最適化継続をプリペンドすることでこれを行います。たとえば、次の例で @f@g にインライン化すると、

define void @f() {
  call void @x()  ;; no deopt state
  call void @y() [ "deopt"(i32 10) ]
  call void @y() [ "deopt"(i32 10), "unknown"(ptr null) ]
  ret void
}

define void @g() {
  call void @f() [ "deopt"(i32 20) ]
  ret void
}

次のようになります

define void @g() {
  call void @x()  ;; still no deopt state
  call void @y() [ "deopt"(i32 20, i32 10) ]
  call void @y() [ "deopt"(i32 20, i32 10), "unknown"(ptr null) ]
  ret void
}

呼び出し元の非最適化状態を呼び出し先の非最適化状態に構文的にプリペンドすることが、意味的には、呼び出し先の非最適化継続の後に呼び出し元の非最適化継続を構成することと同等であるように、非最適化状態を構造化またはエンコードするのは、フロントエンドの責任です。

ファンクレットオペランドバンドル

ファンクレットオペランドバンドルは、"funclet" オペランドバンドルタグで特徴付けられます。これらのオペランドバンドルは、呼び出しサイトが特定のファンクレット内にあることを示します。呼び出しサイトに付与できる "funclet" オペランドバンドルは最大で 1 つであり、正確に 1 つのバンドルオペランドを持つ必要があります。

ファンクレット EH パッドが「エンター」されたが「終了」されていない場合(EH ドキュメントの説明を参照)、

  • "funclet" バンドルがなく、巻き戻ししない組み込み関数の call ではない call または invoke を実行することは未定義の動作であるか、

  • オペランドが最も最近エンターされたがまだ終了していないファンクレット EH パッドではない "funclet" バンドルを持つ必要があります。

同様に、エンターされたがまだ終了していないファンクレット EH パッドがない場合、"funclet" バンドルを持つ call または invoke を実行することは未定義の動作です。

GC 遷移オペランドバンドル

GCトランジションオペランドバンドルは、"gc-transition" オペランドバンドルタグによって特徴付けられます。これらのオペランドバンドルは、あるGC戦略を持つ関数から別のGC戦略を持つ関数へのトランジションとして呼び出しをマークします。GC戦略間のトランジションの調整に、呼び出しサイトでの追加のコード生成が必要な場合、これらのバンドルには、生成されたコードに必要な任意の値を格納できます。詳細については、GCトランジションを参照してください。

バンドルには、GCトランジションコードに渡す必要のある任意のValueのリストが含まれています。これらは、選択DAG内の適切なGC_TRANSITIONノードへのオペランドとして下げられ、渡されます。これらの引数は、呼び出し先の実行前と実行後(ただし、必ずしも実行中ではない)に利用可能である必要があります。

Assumeオペランドバンドル

llvm.assumeのオペランドバンドルを使用すると、パラメータ属性関数属性が、特定の場所で特定の値に対して保持されるといった仮定を表現できます。オペランドバンドルを使用すると、llvm.assumeのブール値引数として表現することが困難または不可能な仮定を表現できます。

Assumeオペランドバンドルは次の形式を持ちます。

"<tag>"([ <arguments>] ])

関数属性またはパラメータ属性の場合、オペランドバンドルは次の制限された形式を持ちます。

"<tag>"([ <holds for value> [, <attribute argument>] ])
  • オペランドバンドルのタグは通常、保持されると想定できる属性の名前です。また、ignoreにすることもでき、このタグには情報は含まれておらず、無視されるべきです。

  • 最初の引数(存在する場合)は、属性が保持される値です。

  • 2番目の引数(存在する場合)は、属性の引数です。

引数がない場合、属性は呼び出し場所のプロパティです。

例:

call void @llvm.assume(i1 true) ["align"(ptr %val, i32 8)]

これにより、オプティマイザは、llvm.assumeへの呼び出し場所で、%valのアライメントが少なくとも8であると想定できます。

call void @llvm.assume(i1 %cond) ["cold"(), "nonnull"(ptr %val)]

これにより、オプティマイザは、llvm.assumeの呼び出し場所がコールドであり、%valがnullでない可能性があると想定できます。

llvm.assumeの引数と同様に、提供された保証のいずれかが実行時に違反された場合、動作は未定義です。

属性は定数引数を想定していますが、Assumeオペランドバンドルには動的な値を指定できます。例:

call void @llvm.assume(i1 true) ["align"(ptr %val, i32 %align)]

オペランドバンドルの値が属性値の要件に違反する場合、次の例外のいずれかが適用されない限り、動作は未定義です。

  • "align" オペランドバンドルは、2のべき乗ではないアライメント(ゼロアライメントを含む)を指定できます。この場合、ポインタ値はnullポインタである必要があり、そうでない場合、動作は未定義です。

関数およびパラメータ属性をエンコードするオペランドバンドルを許可することに加えて、Assumeオペランドバンドルは、separate_storageオペランドバンドルをエンコードすることもできます。これは次の形式を持ちます。

separate_storage(<val1>, <val2>)``

これは、その引数の1つに基づくポインタが、もう1つの引数に基づくポインタとエイリアスできないことを示します。

想定されるプロパティがnonnullのようにブール値としてエンコードできる場合でも、オペランドバンドルを使用してプロパティを表現することは、依然として利点があります。

  • オペランドバンドルを介して表現できる属性は、オプティマイザが使用し、関心を持つプロパティを直接表します。属性をオペランドバンドルとしてエンコードすると、プロパティを表す命令シーケンス(たとえば、nonnullicmp ne ptr %p, null)や、オプティマイザがその命令シーケンスからプロパティを推測する必要性がなくなります。

  • オペランドバンドルを使用してプロパティを表現すると、llvm.assumeでの値の使用を、その使用として簡単に識別できるようになります。これにより、たとえば「使用に依存する」最適化などのヒューリスティックが簡略化され、改善されます。

事前割り当てオペランドバンドル

事前割り当てオペランドバンドルは、"preallocated"オペランドバンドルタグによって特徴付けられます。これらのオペランドバンドルにより、呼び出し引数メモリの割り当てを呼び出しサイトから分離できます。これは、一部のターゲットでMSVCと互換性のある方法で、トリビアルにコピー可能ではないオブジェクトを値で渡すために必要です。呼び出しサイトにアタッチできる"preallocated"オペランドバンドルは最大で1つであり、@llvm.call.preallocated.setupによって生成されたトークンであるバンドルオペランドを1つだけ持つ必要があります。このオペランドバンドルを持つ呼び出しは、関数に入る前にスタックを調整しないでください。これは、@llvm.call.preallocated.*組み込み関数の1つによって行われているためです。

%foo = type { i64, i32 }

...

%t = call token @llvm.call.preallocated.setup(i32 1)
%a = call ptr @llvm.call.preallocated.arg(token %t, i32 0) preallocated(%foo)
; initialize %b
call void @bar(i32 42, ptr preallocated(%foo) %a) ["preallocated"(token %t)]

GCライブオペランドバンドル

"gc-live"オペランドバンドルは、gc.statepoint組み込み関数でのみ有効です。オペランドバンドルには、ガベージコレクタによって更新される可能性のあるガベージコレクトされたオブジェクトへのすべてのポインタを含める必要があります。

下げられると、再配置された値は対応するスタックマップエントリに記録されます。詳細については、組み込み関数の説明を参照してください。

ObjC ARCアタッチされた呼び出しオペランドバンドル

呼び出しの"clang.arc.attachedcall"オペランドバンドルは、呼び出しの直後にマーカー命令と、呼び出しの結果を使用するObjCランタイム関数への呼び出しが続くことを示します。オペランドバンドルは、ランタイム関数への必須ポインタ(@objc_retainAutoreleasedReturnValueまたは@objc_unsafeClaimAutoreleasedReturnValue)を受け取ります。このバンドルを持つ呼び出しの戻り値は、呼び出された関数の戻り型がvoidでない限り、@llvm.objc.clang.arc.noop.useへの呼び出しによって使用されます。その場合、オペランドバンドルは無視されます。

; The marker instruction and a runtime function call are inserted after the call
; to @foo.
call ptr @foo() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ]
call ptr @foo() [ "clang.arc.attachedcall"(ptr @objc_unsafeClaimAutoreleasedReturnValue) ]

このオペランドバンドルは、最終出力で呼び出しの直後にマーカー命令とObjCランタイム呼び出しが続くようにするために必要です。

ポインタ認証オペランドバンドル

ポインタ認証オペランドバンドルは、"ptrauth"オペランドバンドルタグによって特徴付けられます。これらは、ポインタ認証ドキュメントで説明されています。

KCFIオペランドバンドル

間接呼び出しの"kcfi"オペランドバンドルは、呼び出しがランタイム型チェックによって先行され、呼び出しターゲットがオペランドバンドル属性に一致する型識別子で始まることを検証することを示します。例:

call void %0() ["kcfi"(i32 1234)]

Clangは、-fsanitize=kcfiを使用してKCFIオペランドバンドルと必要なメタデータを生成します。

収束制御オペランドバンドル

"convergencectrl"オペランドバンドルは、convergent操作でのみ有効です。存在する場合、オペランドバンドルにはトークン型の値が1つだけ含まれている必要があります。詳細については、収束操作のセマンティクスドキュメントを参照してください。

モジュールレベルインラインアセンブリ

モジュールには、「モジュールレベルインラインアセンブリ」ブロックを含めることができます。これは、GCCの「ファイルスコープインラインアセンブリ」ブロックに対応します。これらのブロックは、内部的にLLVMによって連結され、単一のユニットとして扱われますが、必要に応じて.llファイルで分離できます。構文は非常にシンプルです。

module asm "inline asm code goes here"
module asm "more can go here"

文字列には、印刷不可能な文字をエスケープすることで任意の文字を含めることができます。使用されるエスケープシーケンスは、単純に「\xx」です。ここで、「xx」は数値の2桁の16進コードです。

アセンブリ文字列は、.sファイルを出力する場合でも、LLVMの統合アセンブラ(無効にされていない場合)で解析可能である必要があることに注意してください。

データレイアウト

モジュールは、メモリ内のデータのレイアウト方法を指定するターゲット固有のデータレイアウト文字列を指定できます。データレイアウトの構文は簡単です。

target datalayout = "layout specification"

レイアウト仕様は、マイナス記号(「-」)で区切られた仕様のリストで構成されます。各仕様は文字で始まり、データのレイアウトの側面を定義するために文字の後に他の情報を含めることができます。受け入れられる仕様は次のとおりです。

E

ターゲットがデータをビッグエンディアン形式でレイアウトすることを指定します。つまり、最も重要なビットが最も低いアドレス位置を持ちます。

e

ターゲットがデータをリトルエンディアン形式でレイアウトすることを指定します。つまり、最も重要度の低いビットが最も低いアドレス位置を持ちます。

S<サイズ>

スタックの自然なアライメントをビット単位で指定します。スタック変数のアライメントの昇格は、動的なスタックの再アライメントを避けるため、自然なスタックのアライメントに制限されます。スタックのアライメントは8ビットの倍数でなければなりません。省略した場合、自然なスタックのアライメントはデフォルトで「未指定」となり、アライメントの昇格を妨げることはありません。

P<アドレス 空間>

プログラムメモリに対応するアドレス空間を指定します。ハーバードアーキテクチャでは、これを使用して、関数などをLLVMが配置する場所を指定できます。省略した場合、プログラムメモリアドレス空間はデフォルトのアドレス空間0になり、これは同じ空間にコードとデータを持つフォンノイマンアーキテクチャに対応します。

G<アドレス 空間>

グローバル変数を作成する際にデフォルトで使用されるアドレス空間を指定します。省略した場合、グローバルアドレス空間はデフォルトのアドレス空間0になります。注:アドレス空間のない変数宣言は常にアドレス空間0で作成されます。このプロパティは、追加のコンテキスト情報(LLVMパスなど)なしにグローバルを作成する際に使用されるデフォルト値にのみ影響します。

A<アドレス 空間>

alloca’によって作成されたオブジェクトのアドレス空間を指定します。デフォルトは、デフォルトのアドレス空間0です。

p[n]:<サイズ>:<abi>[:<pref>][:<idx>]

これは、アドレス空間nのポインタのサイズと、その<abi>および<pref>の優先アライメントを指定します。<pref>はオプションであり、デフォルトは<abi>です。4番目のパラメータ<idx>は、アドレス計算に使用されるインデックスのサイズであり、ポインタサイズ以下である必要があります。指定しない場合、デフォルトのインデックスサイズはポインタサイズと同じになります。すべてのサイズはビット単位です。アドレス空間nはオプションで、指定しない場合はデフォルトのアドレス空間0を示します。nの値は[1,2^24)の範囲内である必要があります。

i<サイズ>:<abi>[:<pref>]

これは、指定されたビット<サイズ>の整数型のアライメントを指定します。<サイズ>の値は[1,2^24)の範囲内である必要があります。<pref>はオプションであり、デフォルトは<abi>です。i8の場合、<abi>の値は8と等しくなければなりません。つまり、i8は自然にアライメントされている必要があります。

v<サイズ>:<abi>[:<pref>]

これは、指定されたビット<サイズ>のベクトル型のアライメントを指定します。<サイズ>の値は[1,2^24)の範囲内である必要があります。<pref>はオプションであり、デフォルトは<abi>です。

f<サイズ>:<abi>[:<pref>]

これは、指定されたビット<サイズ>の浮動小数点型のアライメントを指定します。ターゲットでサポートされている<サイズ>の値のみが機能します。32(float)および64(double)はすべてのターゲットでサポートされています。80または128(long doubleの異なるフレーバー)も一部のターゲットでサポートされています。<サイズ>の値は[1,2^24)の範囲内である必要があります。<pref>はオプションであり、デフォルトは<abi>です。

a:<abi>[:<pref>]

これは、集約型のオブジェクトのアライメントを指定します。<pref>はオプションであり、デフォルトは<abi>です。

F<型><abi>

これは、関数ポインタのアライメントを指定します。<型>のオプションは次のとおりです。

  • i:関数ポインタのアライメントは、関数のアライメントとは独立しており、<abi>の倍数です。

  • n:関数ポインタのアライメントは、関数で明示的に指定されたアライメントの倍数であり、<abi>の倍数です。

m:<マングリング>

存在する場合、llvm名が出力でマングルされることを指定します。マングリングエスケープ文字\01で始まるシンボルは、エスケープ文字なしで直接アセンブラに渡されます。マングリングスタイルのオプションは次のとおりです。

  • e:ELFマングリング:プライベートシンボルには.Lプレフィックスが付きます。

  • l:GOFFマングリング:プライベートシンボルには@プレフィックスが付きます。

  • m:Mipsマングリング:プライベートシンボルには$プレフィックスが付きます。

  • o:Mach-Oマングリング:プライベートシンボルにはLプレフィックスが付きます。その他のシンボルには_プレフィックスが付きます。

  • x:Windows x86 COFFマングリング:プライベートシンボルには通常のプレフィックスが付きます。通常のCシンボルには_プレフィックスが付きます。__stdcall__fastcall、および__vectorcallを持つ関数には、パラメータを渡すために使用されるバイト数である@Nを追加するカスタムマングリングがあります。?で始まるC++シンボルは、一切マングルされません。

  • w:Windows COFFマングリング:xに似ていますが、通常のCシンボルには_プレフィックスが付きません。

  • a:XCOFFマングリング:プライベートシンボルにはL..プレフィックスが付きます。

n<サイズ1>:<サイズ2>:<サイズ3>...

これは、ターゲットCPUのネイティブ整数幅のセットをビット単位で指定します。たとえば、32ビットPowerPCの場合はn32、PowerPC 64の場合はn32:64、X86-64の場合はn8:16:32:64が含まれる場合があります。このセットの要素は、ほとんどの一般的な算術演算を効率的にサポートすると見なされます。

ni:<アドレス 空間0>:<アドレス 空間1>:<アドレス 空間2>...

これは、指定されたアドレス空間を持つポインタ型を非整数ポインタ型として指定します。0アドレス空間は、非整数として指定することはできません。

<abi>:<pref>を使用するすべての仕様では、<pref>アライメントの指定はオプションです。省略した場合、先行する:も省略する必要があり、<pref><abi>と等しくなります。

特定のターゲットのデータレイアウトを構築する場合、LLVMはデフォルトの一連の仕様から開始し、その後、datalayoutキーワードの仕様によって(場合によっては)オーバーライドされます。デフォルトの仕様は、このリストに記載されています。

  • e - リトルエンディアン

  • p:64:64:64 - 64ビットアライメントの64ビットポインタ。

  • p[n]:64:64:64 - 他のアドレス空間は、デフォルトのアドレス空間と同じであると想定されます。

  • S0 - 自然なスタックアライメントは未指定

  • i1:8:8 - i1は8ビット(バイト)アライメント

  • i8:8:8 - i8は必須であるため、8ビット(バイト)アライメント

  • i16:16:16 - i16は16ビットアライメント

  • i32:32:32 - i32は32ビットアライメント

  • i64:32:64 - i64のABIアライメントは32ビットですが、優先アライメントは64ビットです

  • f16:16:16 - halfは16ビットアライメント

  • f32:32:32 - floatは32ビットアライメント

  • f64:64:64 - doubleは64ビットアライメント

  • f128:128:128 - quadは128ビットアライメント

  • v64:64:64 - 64ビットベクトルは64ビットアライメント

  • v128:128:128 - 128ビットベクトルは128ビットアライメント

  • a:0:64 - 集約は64ビットアライメント

LLVMが特定の型のアライメントを決定する場合、次の規則を使用します。

  1. 検索された型が仕様の1つと完全に一致する場合、その仕様が使用されます。

  2. 一致するものが見つからず、検索された型が整数型の場合、検索された型のビット幅よりも大きい最小の整数型が使用されます。仕様のいずれもビット幅よりも大きくない場合、最大の整数型が使用されます。たとえば、上記のデフォルトの仕様が与えられた場合、i7型はi8(次に大きい)のアライメントを使用し、i65とi256の両方がi64(最大指定)のアライメントを使用します。

データレイアウト文字列の機能は、期待どおりではない場合があります。特に、これは、コードジェネレータが使用する必要があるアライメントのフロントエンドからの仕様ではありません。

代わりに、指定されている場合、ターゲットデータレイアウトは、最終的なコードジェネレータが期待するものと一致する必要があります。この文字列は、コードを改善するために中間レベルのオプティマイザによって使用され、これは、最終的なコードジェネレータが使用するものと一致する場合にのみ機能します。このターゲット固有の詳細をIRに埋め込まないIRを生成する方法はありません。文字列を指定しない場合、デフォルトの仕様を使用してデータレイアウトが生成され、最適化フェーズは、これらのデフォルトの仕様に関して、ターゲット固有性をIRに導入して動作します。

ターゲットトリプル

モジュールは、ターゲットホストを記述するターゲットトリプル文字列を指定できます。ターゲットトリプルの構文は単純に

target triple = "x86_64-apple-macosx10.7.0"

ターゲットトリプル文字列は、マイナス記号(‘-’)で区切られた一連の識別子で構成されています。標準形式は次のとおりです。

ARCHITECTURE-VENDOR-OPERATING_SYSTEM
ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT

この情報はバックエンドに渡され、適切なアーキテクチャのコードが生成されます。コマンドラインオプション-mtripleを使用して、これをコマンドラインでオーバーライドできます。

オブジェクトのライフタイム

メモリオブジェクト、または単にオブジェクトとは、alloca、ヒープ割り当て呼び出し、グローバル変数定義などのメモリ割り当てによって予約されるメモリ空間の領域のことです。一度割り当てられると、その領域に格納されたバイトは、割り当て値に基づくポインタを介してのみ読み書きできます。オブジェクトに基づかないポインタがオブジェクトを読み書きしようとすると、未定義の動作になります。

メモリオブジェクトのライフタイムとは、そのアクセス可能性を決定するプロパティのことです。特に明記されていない限り、メモリオブジェクトは割り当てられてから生き続け、割り当て解除されると死にます。生きていないメモリオブジェクトにアクセスすることは未定義の動作ですが、getelementptrptrtointicmpなど、オブジェクトを間接参照しない操作は有効な結果を返します。これは、オブジェクトのライフタイムに影響を与える操作をまたいでこれらの命令のコード移動が行われる理由を説明します。スタックオブジェクトのライフタイムは、llvm.lifetime.startllvm.lifetime.endの組み込み関数呼び出しを使用して明示的に指定できます。

ポインタエイリアシング規則

すべてのメモリアクセスは、メモリアクセスのアドレス範囲に関連付けられたポインタ値を介して行う必要があります。そうでない場合、動作は未定義です。ポインタ値は、次の規則に従ってアドレス範囲に関連付けられます。

  • ポインタ値は、それが基づく任意の値に関連付けられたアドレスに関連付けられます。

  • グローバル変数のアドレスは、その変数のストレージのアドレス範囲に関連付けられます。

  • 割り当て命令の結果値は、割り当てられたストレージのアドレス範囲に関連付けられます。

  • デフォルトアドレス空間のヌルポインタは、どのアドレスにも関連付けられません。

  • 任意のアドレス空間のundef値は、どのアドレスにも関連付けられません。

  • ゼロ以外の整数定数またはLLVM内で定義されていない関数から返されたポインタ値は、LLVMによって提供されるメカニズム以外のメカニズムを通じて割り当てられたアドレス範囲に関連付けられる場合があります。そのような範囲は、LLVMによって提供されるメカニズムによって割り当てられたアドレスの範囲と重複してはなりません。

ポインタ値は、次の規則に従って別のポインタ値に基づきます。

  • スカラーgetelementptr操作から形成されたポインタ値は、getelementptrのポインタ型オペランドに基づきます。

  • ベクトルgetelementptr操作の結果のレーンlのポインタは、getelementptrのポインタのベクトル型オペランドのレーンlのポインタに基づきます。

  • bitcastの結果値は、bitcastのオペランドに基づきます。

  • inttoptrによって形成されたポインタ値は、ポインタの値の計算に(直接または間接的に)寄与するすべてのポインタ値に基づきます。

  • 基づく」の関係は推移的です。

この「基づく」の定義は、C99の「基づく」の定義と意図的に似ていますが、わずかに弱いです。

LLVM IRは型をメモリに関連付けません。loadの結果型は、ロード元のメモリのサイズとアラインメント、および値の解釈を示すだけです。storeの最初のオペランド型は、同様にストアのサイズとアラインメントを示すだけです。

したがって、型ベースのエイリアス分析(TBAA、別名-fstrict-aliasing)は、一般的な装飾のないLLVM IRには適用できません。メタデータを使用して、特殊な最適化パスが型ベースのエイリアス分析を実装するために使用できる追加情報をエンコードできます。

ポインタキャプチャ

関数呼び出しと、引数として渡されたり、呼び出し前にメモリに格納されたポインタが与えられた場合、ポインタが呼び出しよりも長く残るポインタの一部をコピーすると、そのポインタは呼び出しによってキャプチャされます。正確には、次の条件の1つ以上が満たされる場合、ポインタはキャプチャされます。

  1. 呼び出しは、情報を持つポインタの任意のビットを場所に格納し、格納されたビットはこの呼び出しの終了後に呼び出し元によって場所から読み取ることができます。

@glb  = global ptr null
@glb2 = global ptr null
@glb3 = global ptr null
@glbi = global i32 0

define ptr @f(ptr %a, ptr %b, ptr %c, ptr %d, ptr %e) {
  store ptr %a, ptr @glb ; %a is captured by this call

  store ptr %b,   ptr @glb2 ; %b isn't captured because the stored value is overwritten by the store below
  store ptr null, ptr @glb2

  store ptr %c,   ptr @glb3
  call void @g() ; If @g makes a copy of %c that outlives this call (@f), %c is captured
  store ptr null, ptr @glb3

  %i = ptrtoint ptr %d to i64
  %j = trunc i64 %i to i32
  store i32 %j, ptr @glbi ; %d is captured

  ret ptr %e ; %e is captured
}
  1. 呼び出しは、情報を持つポインタの任意のビットを場所に格納し、格納されたビットは同期を介して別のスレッドによって場所から安全に読み取ることができます。

@lock = global i1 true

define void @f(ptr %a) {
  store ptr %a, ptr* @glb
  store atomic i1 false, ptr @lock release ; %a is captured because another thread can safely read @glb
  store ptr null, ptr @glb
  ret void
}
  1. 呼び出しの動作は、情報を持つポインタの任意のビットに依存します。

@glb = global i8 0

define void @f(ptr %a) {
  %c = icmp eq ptr %a, @glb
  br i1 %c, label %BB_EXIT, label %BB_CONTINUE ; escapes %a
BB_EXIT:
  call void @exit()
  unreachable
BB_CONTINUE:
  ret void
}
  1. ポインタは、アドレスとして揮発性アクセスで使用されます。

揮発性メモリアクセス

loadstorellvm.memcpyなどの特定のメモリアクセスには、volatileのマークが付いている場合があります。オプティマイザは、volatile操作の数を変更したり、他のvolatile操作に対する実行順序を変更したりしてはなりません。オプティマイザは、非volatile操作に対するvolatile操作の順序を変更できます。これはJavaの「volatile」ではなく、スレッド間の同期動作はありません。

volatileロードまたはストアには、ターゲット固有のセマンティクスが追加される場合があります。すべてのvolatile操作には副作用があり、すべてのvolatile操作は、このモジュール内の通常のロードまたはストアを介してアクセスできない状態を読み取ったり、変更したりできます。揮発性操作は、メモリを指していないアドレス(MMIOレジスタなど)を使用する場合があります。これは、コンパイラがvolatile操作を使用して、そのアドレスへの非volatileアクセスに定義された動作があることを証明できないことを意味します。

揮発性アクセスの許容される副作用は制限されています。特定のアドレスへの非揮発性ストアが正当である場合、揮発性操作はそのアドレスのメモリを変更できます。揮発性操作は、コンパイル中のモジュールがアクセスできる他のメモリを変更することはできません。揮発性操作は、現在のモジュールのコードを呼び出すことはできません。

一般的に(ターゲット固有のコンテキストなしで)、揮発性操作のアドレス空間を変更することはできません。異なるアドレス空間では、無効なポインタを間接参照するときに異なるトラップ動作をする場合があります。

コンパイラは、揮発性操作の後も実行が継続すると想定する可能性があるため、メモリを変更する操作や未定義の動作をする可能性のある操作は、揮発性操作よりも前に移動できます。

前の規則の例外として、コンパイラは揮発性ストア操作の後も実行が継続すると想定することはできません。この制限は、プログラムをクラッシュさせるために意図的に無効なポインタに格納するというCでやや一般的なパターンをサポートするために必要です。将来的には、フロントエンドがこの動作を制御できるようにすることが理にかなっているかもしれません。

IRレベルのvolatileロードとストアは、それらの組み込み関数にvolatileフラグが付けられている場合でも、llvm.memcpyまたはllvm.memmove組み込み関数に安全に最適化することはできません。同様に、バックエンドはターゲットが正当な揮発性ロード/ストア命令を分割またはマージしてはなりません。同様に、IRレベルのvolatileロードとストアは、整数から浮動小数点、またはその逆に変更することはできません。

根拠

プラットフォームは、ネイティブでサポートされているデータ幅の揮発性ロードとストアが単一の命令として実行されることに依存する場合があります。たとえば、Cではこれはネイティブハードウェアサポートを備えた揮発性プリミティブ型のl-valueに当てはまりますが、集約型には必ずしも当てはまりません。フロントエンドはこれらの期待を保持しており、これは意図的にIRでは指定されていません。上記のルールにより、IR変換がフロントエンドと言語の間の契約に違反しないことが保証されます。

並行操作のメモリモデル

LLVM IRは、並列実行のスレッドを開始したり、シグナルハンドラーを登録したりする方法を定義していません。それにもかかわらず、それらを作成するプラットフォーム固有の方法があり、それらの存在下でのLLVM IRの動作を定義します。このモデルは、C++メモリモデルに触発されています。

このモデルのより非公式な紹介については、LLVMアトミック命令と同時実行ガイドを参照してください。

happens-beforeの部分順序を、次の最小の部分順序として定義します。

  • 単一スレッドのプログラム順序のスーパーセットであること、および

  • ab同期するとき、aからbへのエッジを含みます。同期ペアは、pthreadロック、スレッド作成、スレッド結合などのプラットフォーム固有の技術と、アトミック命令によって導入されます。(アトミックメモリ順序制約も参照してください)。

プログラム順序は、スレッドとそのスレッド内で実行されるシグナルの間にhappens-beforeエッジを導入しないことに注意してください。

すべての(定義された)読み取り操作(ロード命令、memcpy、アトミックロード/読み取り-変更-書き込みなど)Rは、(定義された)書き込み操作(ストア命令、アトミックストア/読み取り-変更-書き込み、memcpyなど)によって書き込まれた一連のバイトを読み取ります。このセクションの目的のために、初期化されたグローバルは、問題のメモリの他の読み取りまたは書き込みよりも前にアトミックに行われる初期化子の書き込みがあると見なされます。読み取りRの各バイトについて、Rbyteは同じバイトへの任意の書き込みを認識する場合があります。ただし、

  • write1がwrite2よりも前に発生し、write2がRbyteよりも前に発生する場合、Rbyteはwrite1を認識しません。

  • Rbyteがwrite3よりも前に発生する場合、Rbyteはwrite3を認識しません。

この定義に基づいて、Rbyteは次のように定義されます。

  • Rがvolatileの場合、結果はターゲット依存です。(Volatileは、C/C++でsig_atomic_tをサポートできる保証を与えることになっており、通常のメモリのように動作しないアドレスへのアクセスに使用できます。一般に、スレッド間の同期は提供しません。)

  • それ以外の場合、Rbyteより前に発生する同じバイトへの書き込みがない場合、Rbyteはそのバイトに対してundefを返します。

  • それ以外の場合、Rbyteが1回の書き込みのみを認識できる場合、Rbyteはその書き込みによって書き込まれた値を返します。

  • それ以外の場合、Rがアトミックで、Rbyteが認識できるすべての書き込みがアトミックである場合、書き込まれた値の1つを選択します。選択方法に関する追加の制約については、アトミックメモリ順序制約のセクションを参照してください。

  • それ以外の場合、Rbyteundefを返します。

Rは、読み取った一連のバイトで構成される値を返します。これは、値の一部のバイトがundefである可能性があり、値全体がundefであるとは限らないことを意味します。これは操作の意味を定義するものであり、ターゲットがバイトのシーケンスを読み取るために複数の命令を発行することを意味するものではないことに注意してください。

アトミック組み込み関数が使用されない場合、このモデルは、シングルスレッド実行に必要な制限に加えて、IR変換に1つの制限のみを課すことに注意してください。つまり、通常、そうでなければストアされない可能性のあるバイトへのストアを導入することは許可されません。(具体的には、別のスレッドがアドレスに書き込み、そこから読み取る可能性がある場合、ストアを導入すると、1つの書き込みだけを見ることができるロードが、複数の書き込みを見ることができるロードに変わる可能性があります。)

アトミックメモリー順序制約

アトミック命令(cmpxchgatomicrmwfenceatomic load、およびatomic store)は、同じアドレスに対する他のアトミック命令と同期する命令を決定する順序パラメーターを取ります。これらのセマンティクスは、JavaまたはC++のメモリモデルを実装します。これらの説明が十分に正確でない場合は、これらの仕様を確認してください(アトミックガイドの仕様参照を参照)。fence命令は、アドレスを取らないため、これらの順序を多少異なる方法で扱います。詳細については、その命令のドキュメントを参照してください。

順序制約の簡単な紹介については、LLVMアトミック命令と並行処理ガイドを参照してください。

unordered

読み取ることができる値のセットは、先行発生部分順序によって決定されます。ある操作が値を書き込まない限り、値を読み取ることはできません。これは、Javaの非volatile共有変数をモデル化するのに十分な強力な保証を提供することを目的としています。この順序は、読み取り-変更-書き込み操作には指定できません。これは、それらを興味深い方法でアトミックにするには十分な強さではありません。

monotonic

unorderedの保証に加えて、各アドレスに対するmonotonic操作による変更には、単一の合計順序があります。すべての変更順序は、先行発生順序と互換性がある必要があります。変更順序をプログラム全体のグローバルな合計順序に結合できるという保証はありません(そして、これはしばしば不可能になります)。アトミックな読み取り-変更-書き込み操作(cmpxchgおよびatomicrmw)の読み取りは、書き込む値の直前の変更順序の値を読み取ります。あるアトミック読み取りが、同じアドレスの別のアトミック読み取りより前に発生する場合、後の読み取りでは、同じ値またはアドレスの変更順序で後の値が表示される必要があります。これにより、同じアドレスに対するmonotonic(またはより強力な)操作の並べ替えが禁止されます。あるアドレスが1つのスレッドによってmonotonicに書き込まれ、他のスレッドがそのアドレスを繰り返しmonotonicに読み取る場合、他のスレッドは最終的に書き込みを認識する必要があります。これは、C/C++のmemory_order_relaxedに対応します。

acquire

monotonicの保証に加えて、release操作を使用して同期エッジを形成できます。これは、C/C++のmemory_order_acquireをモデル化することを目的としています。

release

monotonicの保証に加えて、この操作によって書き込まれた値が後でacquire操作によって読み取られる場合、その操作と同期します。さらに、release操作によって書き込まれた値が読み取られる前に、読み取り-変更-書き込み操作によって変更された場合でも、これは発生します。(このような操作のセットは、リリースシーケンスを構成します)。これは、C/C++のmemory_order_releaseに対応します。

acq_rel(acquire+release)

そのアドレスに対してacquire操作とrelease操作の両方として機能します。これは、C/C++のmemory_order_acq_relに対応します。

seq_cst(順次一貫性)

acq_relの保証に加えて(読み取りのみを行う操作の場合はacquire、書き込みのみを行う操作の場合はrelease)、すべてのアドレスに対するすべての順次一貫性のある操作にグローバルな合計順序があります。各順次一貫性のある読み取りは、このグローバル順序で同じアドレスへの最後の先行書き込みを確認します。これは、C/C++のmemory_order_seq_cstおよびJavaのvolatileに対応します。

注:このグローバルな合計順序は、非seq_cstアクセスが関係する場合、先行発生部分順序と完全に一致することが保証されているわけではありません。正確な保証の詳細については、C++標準の[atomics.order]セクションを参照してください。

アトミック操作がsyncscope("singlethread")とマークされている場合、同じスレッド(たとえば、シグナルハンドラー内)で実行されている他の操作のseq_cst合計順序と同期するだけであり、それらにのみ参加します。

アトミック操作がsyncscope("<target-scope>")とマークされている場合、ここで<target-scope>はターゲット固有の同期スコープであり、他の操作のseq_cst合計順序と同期するかどうか、およびそれらに参加するかどうかは、ターゲットに依存します。

それ以外の場合、syncscope("singlethread")またはsyncscope("<target-scope>")とマークされていないアトミック操作は、syncscope("singlethread")またはsyncscope("<target-scope>")とマークされていない他の操作のseq_cst合計順序と同期し、それらに参加します。

浮動小数点環境

デフォルトのLLVM浮動小数点環境では、トラップが無効になっており、ステータスフラグが観察可能ではないと想定されています。したがって、浮動小数点演算には副作用がなく、自由に推測できます。結果は、最も近い丸めモードを想定し、サブノーマルは保持されると想定されます。

これらの仮定が満たされない環境でLLVMコードを実行すると、未定義の動作につながる可能性があります。strictfpおよびdenormal-fp-math属性、および制約付き浮動小数点組み込み関数を使用すると、LLVMの仮定を弱め、デフォルト以外の浮動小数点環境で定義された動作を保証できます。詳細については、それぞれのドキュメントを参照してください。

浮動小数点NaN値の動作

浮動小数点NaN値は、符号ビット、quiet/signalingビット、およびペイロード(quiet/signalingビットを除く仮数の残りを構成する)で構成されます。LLVMは、quiet/signalingビットが1に設定されている場合、静的NaN(QNaN)を示し、0の値は、シグナリングNaN(SNaN)を示すと想定しています。以下では、これを「静音ビット」と呼びます。

浮動小数点値の表現ビットは任意に変化しません。特に、浮動小数点演算が実行されていない場合、NaNの符号、静音ビット、およびペイロードは保持されます。

このセクションの目的上、bitcastと、次の操作は「浮動小数点演算」ではありません。fnegllvm.fabs、およびllvm.copysign。これらの操作は、基になるビット表現に直接作用し、符号ビットを除いて何も変更しません。

特に指定がない限り、浮動小数点演算では、NaN値が返される場合、次の規則が適用されます。結果には非決定的な符号があります。静音ビットとペイロードは、次のオプションのセットから非決定的に選択されます。

  • 静音ビットが設定され、ペイロードがすべてゼロになります。(「優先NaN」ケース)

  • 静音ビットが設定され、ペイロードがNaNである入力オペランドからコピーされます。(「静音化NaN伝播」ケース)

  • 静音ビットとペイロードが、NaNである入力オペランドからコピーされます。(「変更なしNaN伝播」ケース)

  • 静音ビットが設定され、ペイロードがターゲット固有の「追加」の可能なNaNペイロードのセットから選択されます。セットは、入力オペランドの値に依存する場合があります。このセットはx86およびARMでは空ですが、他のアーキテクチャでは空でない場合があります。(たとえば、wasmでは、入力NaNに優先されるすべてのゼロペイロードがない場合、または入力NaNがSNaNである場合、このセットには可能なすべてのペイロードが含まれます。それ以外の場合は空です。SPARCでは、このセットはすべての1つのペイロードで構成されています。)

特に、すべての入力NaNが静的である場合(または入力NaNがない場合)、出力NaNは間違いなく静的です。シグナリングNaN出力は、入力値として提供された場合にのみ発生する可能性があります。たとえば、「fmul SNaN, 1.0」は、QNaNではなくSNaNに単純化できます。同様に、すべての入力NaNが優先される場合(または入力NaNがない場合)、ターゲットに「追加」のNaNペイロードがない場合、出力NaNは優先されることが保証されます。

浮動小数点演算では、すべてのNaNを静的NaNとして扱うことが許可されています。たとえば、「pow(1.0, SNaN)」は1.0に単純化できます。

これとは異なる動作が必要なコードでは、制約付き浮動小数点組み込み関数を使用する必要があります。特に、制約付き組み込み関数は「変更なしNaN伝播」ケースを除外します。QNaNを返すことが保証されています。

残念ながら、修正が困難または不可能な問題のため、LLVMは一部のアーキテクチャで独自の仕様に違反しています。

  • SSE2 が有効になっていない x86-32 では、浮動小数点演算の実行時に浮動小数点値を x86_fp80 に変換してから元に戻すことがあります。これにより、予期される精度とは異なる結果になったり、NaN 値が変更されたりする可能性があります。最適化によって矛盾する前提が立てられる可能性があるため、これが原因で任意の間違ったコンパイルが発生する可能性があります。issue #44218 を参照してください。

  • x86-32 (SSE2 が有効になっている場合でも) では、一部の呼び出し規約において、関数から返される値でそのような変換が暗黙的に実行されることがあります。issue #66803 を参照してください。

  • 古い MIPS バージョンでは、quiet/signaling ビットの極性が逆になっており、LLVM はこれを正しく表現していません。issue #60796 を参照してください。

Fast-Math フラグ

LLVM IR 浮動小数点演算 (fneg, fadd, fsub, fmul, fdiv, frem, fcmp), phi, select および call では、通常は安全でない浮動小数点変換を有効にするために、以下のフラグを使用できます。

fast

このフラグは、すべての fast-math フラグを一度に指定するための省略形であり、それらすべてを使用すること以上の追加のセマンティクスはありません。

nnan

NaN なし - 最適化で、引数と結果が NaN ではないと仮定することを許可します。引数が NaN である場合、または結果が NaN になる場合は、代わりに poison 値 が生成されます。

ninf

No Infs - 最適化で、引数と結果が +/-Inf ではないと仮定することを許可します。引数が +/-Inf である場合、または結果が +/-Inf になる場合は、代わりに poison 値 が生成されます。

nsz

符号付きゼロなし - 最適化で、ゼロ引数またはゼロ結果の符号を重要でないものとして扱うことを許可します。これは、-0.0 が poison であり、/または操作に存在しないことが保証されていることを意味するものではありません。

書き換えベースのフラグ

以下のフラグには、書き換えベースのセマンティクスがあります。これらのフラグを使用すると、複数の連続しない命令を含む可能性のある式を、代替命令に書き換えることができます。式に複数の命令が含まれる場合、すべての命令に必須の書き換えベースのフラグが存在する必要があり、書き換えられた命令には通常、入力命令に存在するフラグの共通部分が含まれます。

次の例では、@orig の本体にある浮動小数点式には、contractreassoc が共通して含まれているため、@target の本体にある式に書き換えられた場合、新しい命令はすべて、結果としてそれらの 2 つのフラグのみを取得します。arcp は式の命令の 1 つにのみ存在するため、変換された式には存在しません。さらに、ここでの再結合は、両方の命令に reassoc フラグがある場合にのみ正当です。1 つにしか存在しない場合、変換を行うのは正当ではありません。

define double @orig(double %a, double %b, double %c) {
  %t1 = fmul contract reassoc double %a, %b
  %val = fmul contract reassoc arcp double %t1, %c
  ret double %val
}

define double @target(double %a, double %b, double %c) {
  %t1 = fmul contract reassoc double %b, %c
  %val = fmul contract reassoc double %a, %t1
  ret double %val
}

これらの規則は、他の fast-math フラグには適用されません。nnan のようなフラグが書き換えられた命令のいずれかまたはすべてに存在するかどうかは、元のフラグを考慮すると、命令に NaN 入力または出力を持つ可能性が存在するかどうかに基づいています。

arcp

除算を逆数の乗算として扱うことを許可します。具体的には、これにより、a / ba * (1.0 / b) と同等と見なされることが許可され (これはその後、コード移動の影響を受ける可能性があります)、a / (b / c)a * (c / b) と同等と見なされることが許可されます。これらの書き換えはどちらの方向にも適用できます。a * (c / b)a / (b / c) に書き換えることができます。

contract

浮動小数点の縮約を許可します (たとえば、乗算の後に加算が続くものを、融合された乗算加算に融合するなど)。これは、任意の縮約を形成するための再結合を有効にするものではありません。たとえば、(a*b) + (c*d) + e(a*b) + ((c*d) + e) に変換して、2 つの fma 操作を作成することはできません。

afn

近似関数 - 関数 (sin、log、sqrt など) の近似計算の代用を許可します。これが LLVM の組み込み数学関数に適用できる場所については、浮動小数点組み込みの定義を参照してください。

reassoc

浮動小数点命令の再結合変換を許可します。これにより、浮動小数点の結果が大幅に変更される可能性があります。

Use-list 順序ディレクティブ

Use-list ディレクティブは、各 use-list のメモリ内順序をエンコードし、順序を再作成できるようにします。<order-indexes> は、参照される値の使用に割り当てられるインデックスのカンマ区切りリストです。参照される値の use-list は、これらのインデックスによってすぐにソートされます。

Use-list ディレクティブは、関数スコープまたはグローバルスコープで表示される場合があります。それらは命令ではなく、IR のセマンティクスには影響しません。関数スコープにある場合、最後の基本ブロックのターミネータの後に表示される必要があります。

基本ブロックのアドレスが blockaddress() 式を介して取得される場合、uselistorder_bb を使用して、関数のスコープ外から use-list の順序を変更できます。

構文:

uselistorder <ty> <value>, { <order-indexes> }
uselistorder_bb @function, %block { <order-indexes> }
:

define void @foo(i32 %arg1, i32 %arg2) {
entry:
  ; ... instructions ...
bb:
  ; ... instructions ...

  ; At function scope.
  uselistorder i32 %arg1, { 1, 0, 2 }
  uselistorder label %bb, { 1, 0 }
}

; At global scope.
uselistorder ptr @global, { 1, 2, 0 }
uselistorder i32 7, { 1, 0 }
uselistorder i32 (i32) @bar, { 1, 0 }
uselistorder_bb @foo, %bb, { 5, 1, 3, 2, 0, 4 }

ソースファイル名

ソースファイル名文字列は、元のモジュール識別子に設定されます。これは、たとえば、clang フロントエンドを介してソースからコンパイルするときは、コンパイルされたソースファイルの名前になります。その後、IR とビットコードを通じて保持されます。

これは現在、プロファイルデータで使用されるローカル関数のための一貫性のある一意のグローバル識別子を生成するために必要です。この識別子は、ソースファイル名をローカル関数名の前に付加します。

ソースファイル名の構文は単純に

source_filename = "/path/to/source.c"

型システム

LLVM 型システムは、中間表現の最も重要な機能の 1 つです。型付けされていることで、変換前に側面に余分な分析を行う必要なしに、中間表現で直接多くの最適化を実行できます。強力な型システムにより、生成されたコードを読みやすくなり、通常の 3 アドレスコード表現では実行できない新しい分析と変換が可能になります。

Void 型

概要:

void 型は値を表さず、サイズもありません。

構文:

void

関数型

概要:

関数型は、関数のシグネチャと考えることができます。これは、戻り型と仮パラメーター型のリストで構成されます。関数型の戻り型は、label 型と metadata 型を除き、void 型またはファーストクラス型です。

構文:

<returntype> (<parameter list>)

…ここで、'<parameter list>' は、型の指定子のカンマ区切りリストです。オプションで、パラメーターリストには、関数が可変数の引数を取ることを示す型 ... を含めることができます。可変引数関数は、可変引数処理組み込み関数を使用して引数にアクセスできます。'<returntype>' は、label 型と metadata 型を除く任意の型です。

:

i32 (i32)

i32 を受け取り、i32 を返す関数

i32 (ptr, ...)

少なくとも 1 つの pointer 引数を受け取り、整数を返す可変引数関数。これは、LLVM における printf のシグネチャです。

{i32, i32} (i32)

i32 を引数に取り、2つの i32 値を含む構造体を返す関数

ファーストクラス型

ファーストクラス型は、おそらく最も重要なものです。これらの型の値は、命令によって生成できる唯一の値です。

単一値型

これらは、CodeGenの観点からレジスタ内で有効な型です。

整数型
概要:

整数型は、目的の整数型に対して任意のビット幅を指定するだけの非常にシンプルな型です。1ビットから223(約800万)ビットまでの任意のビット幅を指定できます。

構文:

iN

整数が占有するビット数は、N 値によって指定されます。

例:

i1

単一ビットの整数。

i32

32ビット整数。

i1942652

100万ビットを超える非常に大きな整数。

浮動小数点型

説明

half

16ビット浮動小数点値

bfloat

16ビットの「脳」浮動小数点値(7ビットの仮数)。floatと同じ数の指数ビットを提供し、ダイナミックレンジを一致させますが、精度は大幅に低下します。IntelのAVX-512 BF16拡張やArmのARMv8.6-A拡張などで使用されます。

float

32ビット浮動小数点値

double

64ビット浮動小数点値

fp128

128ビット浮動小数点値(113ビットの仮数)

x86_fp80

80ビット浮動小数点値(X87)

ppc_fp128

128ビット浮動小数点値(2つの64ビット)

half、float、double、fp128のバイナリ形式は、それぞれbinary16、binary32、binary64、binary128に対するIEEE-754-2008仕様に対応します。

X86_amx 型
概要:

x86_amx型は、x86マシン上のAMXタイルレジスタに保持される値を表します。許可される操作は非常に限られています。ストライドロードとストア、ゼロ、ドット積のいくつかの組み込み関数のみが許可されています。この型には命令は許可されていません。この型には引数、配列、ポインタ、ベクトル、または定数はありません。

構文:

x86_amx
ポインタ型
概要:

ポインタ型 ptr は、メモリーロケーションを指定するために使用されます。ポインタは通常、メモリー内のオブジェクトを参照するために使用されます。

ポインタ型には、ポインタが指すオブジェクトが常駐する番号付きアドレス空間を定義するオプションのアドレス空間属性を含めることができます。たとえば、ptr addrspace(5) はアドレス空間5へのポインタです。整数定数に加えて、addrspacedatalayout文字列で定義されたアドレス空間の1つを参照することもできます。addrspace("A") はallocaアドレス空間を使用し、addrspace("G") はデフォルトのグローバルアドレス空間を使用し、addrspace("P") はプログラムアドレス空間を使用します。

デフォルトのアドレス空間は番号ゼロです。

ゼロ以外のアドレス空間のセマンティクスは、ターゲット固有です。逆参照不可能なポインタを介したメモリーアクセスは、どのアドレス空間でも未定義の動作です。ビット値が0のポインタは、関数にnull_pointer_is_valid 属性がマークされていない限り、アドレス空間0でのみ逆参照不可能であると想定されます。

異なるアドレス空間を持つポインタを介してオブジェクトにアクセスできることが証明された場合、アクセスはそのアドレス空間を使用するように変更される場合があります。操作が volatile の場合は例外が適用されます。

LLVM 15より前では、ポインタ型は i8*[4 x i32]*、または i32 (i32*)*などのポインティ型も指定していました。LLVM 15では、このような「型付きポインタ」は、非デフォルトオプションの下で引き続きサポートされています。詳細については、不透明ポインタのドキュメントを参照してください。

ターゲット拡張型
概要:

ターゲット拡張型は、最適化を通じて保持する必要があるが、それ以外の場合はコンパイラに対して一般的に不透明な型を表します。これらは、関数のパラメーターまたは引数として、phi または select 命令で使用できます。一部の型は alloca 命令またはグローバル値としても使用でき、対応して、それらに対して load および store 命令を使用することが合法です。これらの型の完全なセマンティクスは、ターゲットによって定義されます。

ターゲット拡張型が持つことができる定数は、zeroinitializerundef、および poison のみです。ターゲット拡張型の他の可能な値は、ターゲット固有の組み込み関数や関数から発生する可能性があります。

これらの型を他の型に変換することはできません。そのため、bitcast 命令(ソース型またはターゲット型として)で使用することは合法ではありません。また、ptrtoint または inttoptr 命令で使用することも合法ではありません。同様に、icmp 命令で使用することも合法ではありません。

ターゲット拡張型には、名前とオプションの型または整数パラメーターがあります。名前とパラメーターの意味は、ターゲットによって定義されます。LLVM IRで定義する場合、すべての型パラメーターは、すべての整数パラメーターよりも前に記述する必要があります。

特定のターゲット拡張型は、特定のプロパティを持つものとしてLLVMに登録されます。これらのプロパティを使用すると、グローバル変数の型である場合や、zeroinitializer 定数が有効であるなど、特定のコンテキストで型が表示されないように制限できます。型のプロパティの完全なリストは、llvm::TargetExtType::Propertydoxygen)のドキュメントにあります。

構文:

target("label")
target("label", void)
target("label", void, i32)
target("label", 0, 1, 2)
target("label", void, i32, 0, 1, 2)
ベクター型
概要:

ベクター型は、要素のベクターを表す単純な派生型です。ベクター型は、単一の命令(SIMD)を使用して複数のプリミティブデータが並行して操作される場合に使用されます。ベクター型には、サイズ(要素数)、基礎となるプリミティブデータ型、およびコンパイル時に正確なハードウェアベクター長が不明なベクターを表すためのスケーラブルなプロパティが必要です。ベクター型はファーストクラスと見なされます。

メモリーレイアウト:

一般的に、ベクター要素は、配列型と同じ方法でメモリーにレイアウトされます。このような類似点は、ベクター要素がバイトサイズである限り正常に機能します。ただし、ベクターの要素がバイトサイズではない場合、少し複雑になります。レイアウトを記述する1つの方法は、<N x iM>などのベクターがN*Mビットの整数型にビットキャストされたときに何が起こるかを記述し、そのような整数をメモリーに格納するためのルールに従うことです。

ベクター型からスカラー整数型へのビットキャストでは、要素が(パディングなしで)パックされていると見なされます。要素が整数に挿入される順序は、エンディアンに依存します。リトルエンディアンの場合、要素ゼロが整数の最下位ビットに入れられ、ビッグエンディアンの場合、要素ゼロが最上位ビットに入れられます。

例として <i4 1, i4 2, i4 3, i4 5> のようなベクターを使用し、ベクターストアをビットキャストに続いて整数ストアで置き換えることができるという類似性とともに、ビッグエンディアンの場合、次のようになります。

%val = bitcast <4 x i4> <i4 1, i4 2, i4 3, i4 5> to i16

; Bitcasting from a vector to an integral type can be seen as
; concatenating the values:
;   %val now has the hexadecimal value 0x1235.

store i16 %val, ptr %ptr

; In memory the content will be (8-bit addressing):
;
;    [%ptr + 0]: 00010010  (0x12)
;    [%ptr + 1]: 00110101  (0x35)

リトルエンディアンの場合の同じ例

%val = bitcast <4 x i4> <i4 1, i4 2, i4 3, i4 5> to i16

; Bitcasting from a vector to an integral type can be seen as
; concatenating the values:
;   %val now has the hexadecimal value 0x5321.

store i16 %val, ptr %ptr

; In memory the content will be (8-bit addressing):
;
;    [%ptr + 0]: 00100001  (0x21)
;    [%ptr + 1]: 01010011  (0x53)

<N*M> がバイトサイズで均等に割り切れない場合、正確なメモリーレイアウトは指定されていません(同じサイズの整数型の場合と同じです)。これは、型のサイズが型のストアサイズよりも小さい場合、ターゲットごとにパディングが異なる位置に配置される可能性があるためです。

構文:

< <# elements> x <elementtype> >          ; Fixed-length vector
< vscale x <# elements> x <elementtype> > ; Scalable vector

要素の数は、0より大きい定数整数値です。elementtypeは、任意の整数、浮動小数点、またはポインタ型にすることができます。サイズがゼロのベクターは許可されていません。スケーラブルなベクターの場合、要素の合計数は、指定された要素数の定数倍(vscaleと呼ばれます)です。vscaleは、コンパイル時に不明な正の整数であり、実行時にすべてのスケーラブルなベクターに対して同じハードウェア依存の定数です。したがって、特定の拡張可能なベクター型のサイズは、バイト単位の正確なサイズが実行時まで決定できない場合でも、IR内では定数です。

:

<4 x i32>

4つの32ビット整数値のベクター。

<8 x float>

8つの32ビット浮動小数点値のベクター。

<2 x i64>

2つの64ビット整数値のベクター。

<4 x ptr>

4つのポインタのベクター

<vscale x 4 x i32>

4つの32ビット整数値の倍数のベクター。

ラベル型

概要:

ラベル型は、コードラベルを表します。

構文:

label

トークン型

概要:

トークン型は、値が命令に関連付けられているが、値のすべての使用がそれを内観または不明瞭にしようとすべきでない場合に使用されます。そのため、トークン型の phi または select を持つことは適切ではありません。

構文:

token

メタデータ型

概要:

メタデータ型は、埋め込みメタデータを表します。メタデータから派生型を作成することはできません。関数の引数を除きます。

構文:

metadata

集約型

集約型は、複数のメンバー型を含むことができる派生型のサブセットです。配列構造体は集約型です。ベクトルは集約型とはみなされません。

配列型
概要:

配列型は、メモリ内に要素を順番に配置する非常に単純な派生型です。配列型には、サイズ(要素数)と基になるデータ型が必要です。

構文:

[<# elements> x <elementtype>]

要素数は定数整数値です。elementtype は、サイズを持つ任意の型を使用できます。

:

[40 x i32]

40個の32ビット整数値の配列。

[41 x i32]

41個の32ビット整数値の配列。

[4 x i8]

4個の8ビット整数値の配列。

以下に、多次元配列の例をいくつか示します。

[3 x [4 x i32]]

32ビット整数値の3x4配列。

[12 x [10 x float]]

単精度浮動小数点値の12x10配列。

[2 x [3 x [4 x i16]]]

16ビット整数値の2x3x4配列。

静的な型によって暗示される配列の末尾を超えたインデックス付けに制限はありません(ただし、場合によっては、割り当てられたオブジェクトの境界を超えたインデックス付けには制限があります)。これは、LLVMでは、ゼロ長の配列型を使用して、単一ディメンションの「可変サイズ配列」のアドレス指定を実装できることを意味します。LLVMでの「パスカルスタイルの配列」の実装では、たとえば、型「{ i32, [0 x float]}」を使用できます。

構造体型
概要:

構造体型は、メモリ内でデータメンバーの集合をまとめて表現するために使用されます。構造体の要素には、サイズを持つ任意の型を使用できます。

メモリ内の構造体には、'load' および 'store' を使用して、'getelementptr' 命令でフィールドへのポインタを取得してアクセスします。レジスタ内の構造体には、'extractvalue' および 'insertvalue' 命令を使用してアクセスします。

構造体は、オプションで「パック」された構造体である場合があり、これは、構造体の配置が1バイトであり、要素間にパディングがないことを示します。非パック構造体では、フィールド型間のパディングは、モジュールの DataLayout 文字列で定義されているように挿入されます。これは、基になるコードジェネレーターが予期するものと一致する必要があります。

構造体は、「リテラル」または「識別」のいずれかになります。リテラル構造体は、他の型(例:[2 x {i32, i32}])でインラインで定義されます。一方、識別された型は常に名前付きで最上位で定義されます。リテラル型は、その内容によって一意にされ、記述する方法がないため、再帰的または不透明になることはありません。識別された型は、再帰的、不透明にでき、一意になることはありません。

構文:

%T1 = type { <type list> }     ; Identified normal struct type
%T2 = type <{ <type list> }>   ; Identified packed struct type
:

{ i32, i32, i32 }

3つの i32 値のトリプル。

{ float, ptr }

ペア。最初の要素は float で、2番目の要素は ポインタです。

<{ i8, i32 }>

サイズが5バイトであることがわかっているパック構造体。

不透明な構造体型
概要:

不透明な構造体型は、本体が指定されていない構造体型を表すために使用されます。これは、(たとえば)Cの前方宣言された構造体の概念に対応します。名前付き(%X)または名前なし(%52)にすることができます。

構文:

%X = type opaque
%52 = type opaque
:

opaque

不透明な型。

定数

LLVMには、いくつかの異なる基本型の定数があります。このセクションでは、それらすべてとその構文について説明します。

単純な定数

ブール定数

文字列 ‘true’ および ‘false’ は、両方とも i1 型の有効な定数です。

整数定数

標準整数(「4」など)は、整数型の定数です。10進数または16進数のいずれかにできます。10進整数には、負の整数を表すために - をプレフィックスとして付けることができます(例:‘-1234’)。16進整数には、それぞれ符号なしまたは符号付きを示すために、u または s をプレフィックスとして付ける必要があります。例: ‘u0x8000’ は 32768 を与え、‘s0x8000’ は -32768 を与えます。

16進整数は、アクティブなビット数、つまりビット幅から先頭のゼロの数を引いた数から符号拡張されることに注意してください。したがって、型 ‘i16’ の ‘s0x0001’ は 1 ではなく -1 になります。

浮動小数点定数

浮動小数点定数は、標準の10進数表記(例:123.421)、指数表記(例:1.23421e+2)、またはより正確な16進数表記(以下を参照)を使用します。アセンブラは、浮動小数点定数の正確な10進数値を必要とします。たとえば、アセンブラは 1.25 を受け入れますが、1.3 はバイナリで繰り返し10進数であるため、1.3 を拒否します。浮動小数点定数には、浮動小数点型が必要です。

NULLポインタ定数

識別子 ‘null’ はNULLポインタ定数として認識され、ポインタ型である必要があります。

トークン定数

識別子 ‘none’ は空のトークン定数として認識され、トークン型である必要があります。

定数の直感的でない表記の1つは、浮動小数点定数の16進数形式です。たとえば、形式 ‘double    0x432ff973cafa8000’ は(読み取りにくいですが)‘double 4.5e+15’ と同等です。16進数の浮動小数点定数が必要な場合(および、逆アセンブラによって生成される唯一の場合)は、浮動小数点定数を出力する必要があるが、妥当な桁数の10進浮動小数点数として表現できない場合のみです。たとえば、NaN、無限大、およびその他の特殊値は、アセンブリおよび逆アセンブリで定数のビットが変更されないように、IEEE 16進数形式で表されます。

16進数形式を使用する場合、bfloat、half、float、および double 型の定数は、上記に示す16桁の形式を使用して表されます(これは、double の IEEE754 表現と一致します)。ただし、bfloat、half、および float の値は、それぞれ bfloat、IEEE 754 half、および IEEE 754 単精度として正確に表現できる必要があります。16進数形式は常に long double に使用され、long double には3つの形式があります。x86 で使用される 80 ビット形式は、0xK の後に20桁の16進数として表されます。PowerPC で使用される 128 ビット形式(隣接する2つのdouble)は、0xM の後に32桁の16進数として表されます。IEEE 128 ビット形式は、0xL の後に32桁の16進数として表されます。long double は、ターゲットの long double 形式と一致する場合にのみ機能します。IEEE 16ビット形式(半精度)は、0xH の後に4桁の16進数として表されます。bfloat 16ビット形式は、0xR の後に4桁の16進数として表されます。すべての16進数形式はビッグエンディアンです(符号ビットは左側)。

x86_amx 型の定数はありません。

複合定数

複合定数は、単純な定数とより小さい複合定数の(潜在的に再帰的な)組み合わせです。

構造体定数

構造体定数は、構造体型の定義と同様の表記(中括弧({})で囲まれた要素のコンマ区切りリスト)で表されます。たとえば、「{ i32 4, float 17.0, ptr @G }」などです。ここで、「@G」は「@G = external global i32」として宣言されています。構造体定数には、構造体型が必要であり、要素の数と型は型で指定されたものと一致する必要があります。

配列定数

配列定数は、配列型の定義と同様の表記(角括弧([])で囲まれた要素のコンマ区切りリスト)で表されます。たとえば、「[ i32 42, i32 11, i32 74 ]」などです。配列定数には、配列型が必要であり、要素の数と型は型で指定されたものと一致する必要があります。特殊なケースとして、文字配列定数は、c プレフィックスを使用して二重引用符で囲まれた文字列としても表すことができます。例:‘c"Hello World\0A\00"’。

ベクトル定数

ベクトル定数は、ベクトル型の定義と同様の表記(不等号記号(<>)で囲まれた要素のコンマ区切りリスト)で表されます。たとえば、「< i32 42, i32 11, i32 74, i32 100 >」などです。ベクトル定数には、ベクトル型が必要であり、要素の数と型は型で指定されたものと一致する必要があります。

同じ定数値を持つ要素を持つベクトルを作成する場合、推奨される構文は splat (<Ty> Val) です。例:「splat (i32 11)」。これらのベクトル定数は、ベクター型を持ち、要素型は splat オペランドと一致する必要があります。

ゼロ初期化

文字列 'zeroinitializer' は、スカラー型や集約型を含む任意の型の値をゼロに初期化するために使用できます。これは、(例えば、大きな配列のような) 大きなゼロ初期化子を記述する手間を省くためによく使用され、常に明示的なゼロ初期化子を使用することと完全に同等です。

メタデータノード

メタデータノードは、型のない定数タプルです。例:「!{!0, !{!2, !0}, !"test"}」。メタデータは定数値を参照できます。例:「!{!0, i32 0, ptr @global, ptr @function, !"str"}」。命令ストリームの一部として解釈されることを意図した他の型付き定数とは異なり、メタデータはデバッグ情報などの追加情報を付加する場所です。

グローバル変数と関数アドレス

グローバル変数関数のアドレスは、常に暗黙的に有効な (リンク時) 定数です。これらの定数は、グローバルの識別子が使用されるときに明示的に参照され、常にポインター型を持ちます。例えば、以下は合法な LLVM ファイルです。

@X = global i32 17
@Y = global i32 42
@Z = global [2 x ptr] [ ptr @X, ptr @Y ]

未定義の値

文字列 'undef' は定数が期待される任意の場所で使用でき、値のユーザーが不特定のビットパターンを受け取る可能性があることを示します。未定義の値は、('label' または 'void' を除く) 任意の型を持つことができ、定数が許可される任意の場所で使用できます。

注記

可能な場合は、'undef' の代わりに (次のセクションで説明する) 'poison' 値を使用する必要があります。 Poison 値は undef よりも強力で、より多くの最適化を可能にします。 'undef' が存在するだけで特定の最適化がブロックされます (以下の例を参照)。

未定義の値は、プログラムがどのような値を使用しても適切に定義されることをコンパイラに示すため、有用です。これにより、コンパイラはより自由に最適化できます。(疑似 IR での) 有効な (潜在的に驚くべき) 変換の例を以下に示します。

  %A = add %X, undef
  %B = sub %X, undef
  %C = xor %X, undef
Safe:
  %A = undef
  %B = undef
  %C = undef

出力ビットがすべて undef ビットの影響を受けるため、これは安全です。どの出力ビットも、入力ビットに応じて 0 または 1 になる可能性があります。

  %A = or %X, undef
  %B = and %X, undef
Safe:
  %A = -1
  %B = 0
Safe:
  %A = %X  ;; By choosing undef as 0
  %B = %X  ;; By choosing undef as -1
Unsafe:
  %A = undef
  %B = undef

これらの論理演算には、入力によって常に影響を受けるわけではないビットがあります。たとえば、%X に 0 ビットがある場合、'and' 演算の出力は、'undef' からの対応するビットが何であれ、そのビットに対して常に 0 になります。そのため、'and' の結果が 'undef' であると最適化または仮定することは安全ではありません。ただし、'undef' のすべてのビットが 0 であると仮定して、'and' を 0 に最適化するのは安全です。同様に、'or' への 'undef' オペランドのすべてのビットが設定されていると仮定することで、'or' を -1 に畳み込むことができます。

  %A = select undef, %X, %Y
  %B = select undef, 42, %Y
  %C = select %X, %Y, undef
Safe:
  %A = %X     (or %Y)
  %B = 42     (or %Y)
  %C = %Y     (if %Y is provably not poison; unsafe otherwise)
Unsafe:
  %A = undef
  %B = undef
  %C = undef

この一連の例は、未定義の 'select' (および条件付き分岐) 条件はどちらの方向にも行くことができるが、2 つのオペランドのいずれかから来る必要があることを示しています。%A の例では、%X%Y の両方がロービットをクリアしていることがわかっている場合、%A はロービットをクリアする必要があります。ただし、%C の例では、%Y が明らかに 'poison' でない場合、オプティマイザは 'undef' オペランドが %Y と同じであると仮定することができ、'select' 全体を削除することができます。これは、'poison' が 'undef' よりも強力であるためです。

  %A = xor undef, undef

  %B = undef
  %C = xor %B, %B

  %D = undef
  %E = icmp slt %D, 4
  %F = icmp gte %D, 4

Safe:
  %A = undef
  %B = undef
  %C = undef
  %D = undef
  %E = undef
  %F = undef

この例は、2 つの 'undef' オペランドが必ずしも同じではないことを示しています。これは、X が未定義であっても、「X^X」が常にゼロであると仮定する人にとっては驚くかもしれません (C のセマンティクスにも一致します)。これはいくつかの理由から真実ではありませんが、簡単に言えば、'undef'「変数」は「有効期間」中に任意に値を変更できるということです。これは、変数が実際に有効期間を持たないためです。代わりに、値は論理的に、必要なときに周囲にある任意のレジスタから読み取られるため、値は必ずしも時間的に一貫しているとは限りません。実際、%A%C は同じセマンティクスを持つ必要があり、そうしないと、コア LLVM の「すべての使用箇所を置換」という概念が成り立ちません。

('undef' の場合でも) 特定のレジスタのすべての使用で同じ値が観測されるようにするには、freeze 命令を使用できます。

  %A = sdiv undef, %X
  %B = sdiv %X, undef
Safe:
  %A = 0
b: unreachable

これらの例は、未定義の値未定義の動作の間の重要な違いを示しています。未定義の値 (「undef」など) は、任意のビットパターンを持つことが許可されています。これは、'undef' が 0 になる可能性があり、ゼロを任意の値で除算した結果はゼロであるため、%A 演算を「0」に定数畳み込みできることを意味します。ただし、2 番目の例では、より積極的な仮定を立てることができます。undef は任意の値にできるため、それがゼロになる可能性があると仮定できます。ゼロによる除算は未定義の動作であるため、演算がまったく実行されないと仮定できます。これにより、除算とその後ろのすべてのコードを削除できます。未定義の演算は「発生し得ない」ため、オプティマイザはそれがデッドコードで発生すると仮定できます。

a:  store undef -> %X
b:  store %X -> undef
Safe:
a: <deleted>     (if the stored value in %X is provably not poison)
b: unreachable

未定義の値の格納は、何の効果もないと仮定できます。値が既にそこにあったものと一致するビットで上書きされると仮定できます。この議論は、格納された値が明らかに poison でない場合にのみ有効です。ただし、未定義の場所に格納すると、任意のメモリを破壊する可能性があり、そのため、未定義の動作になります。

未定義の値に対する分岐は、未定義の動作です。これは、相関値伝播やグローバル値番号付けなど、述語を構築するために分岐条件に依存する最適化を説明しています。 switch 命令の場合、分岐条件はフリーズする必要があります。そうしないと未定義の動作になります。

Unsafe:
  br undef, BB1, BB2 ; UB

  %X = and i32 undef, 255
  switch %X, label %ret [ .. ] ; UB

  store undef, ptr %ptr
  %X = load ptr %ptr ; %X is undef
  switch i8 %X, label %ret [ .. ] ; UB

Safe:
  %X = or i8 undef, 255 ; always 255
  switch i8 %X, label %ret [ .. ] ; Well-defined

  %X = freeze i1 undef
  br %X, BB1, BB2 ; Well-defined (non-deterministic jump)

Poison 値

Poison 値は、誤った操作の結果です。投機的実行を容易にするために、多くの命令は不正なオペランドが指定されたときに即座に未定義の動作を呼び出すのではなく、代わりに poison 値を返します。文字列 'poison' は、定数が期待される任意の場所で使用でき、add などの操作で nsw フラグを使用して poison 値を生成できます。

ほとんどの命令は、引数のいずれかが 'poison' の場合、'poison' を返します。注目すべき例外は、select 命令です。poison の伝播は、freeze 命令で停止できます。

poison 値を undef 値または型の任意の値で置き換えることは正しいです。

これは、未定義の動作を引き起こす値を操作オペランドとして poison 値を使用した場合、即座に未定義の動作が発生することを意味します。特に、これには以下が含まれますが、これらに限定されません。

  • loadstore、またはその他のポインター逆参照命令 (アドレス空間に関係なく) のポインターオペランド。

  • udivsdivurem、または srem 命令の除数オペランド。

  • br 命令の条件オペランド。

  • call または invoke 命令の呼び出し先オペランド。

  • 関数または呼び出しサイトが対応する位置に noundef 属性を持っている場合、call または invoke 命令のパラメーターオペランド。

  • 関数または呼び出し側の呼び出し箇所が戻り値の位置にnoundef属性を持つ場合、ret命令のオペランド。

以下にいくつかの例を示します。

entry:
  %poison = sub nuw i32 0, 1           ; Results in a poison value.
  %poison2 = sub i32 poison, 1         ; Also results in a poison value.
  %still_poison = and i32 %poison, 0   ; 0, but also poison.
  %poison_yet_again = getelementptr i32, ptr @h, i32 %still_poison
  store i32 0, ptr %poison_yet_again   ; Undefined behavior due to
                                       ; store to poison.

  store i32 %poison, ptr @g            ; Poison value stored to memory.
  %poison3 = load i32, ptr @g          ; Poison value loaded back from memory.

  %poison4 = load i16, ptr @g          ; Returns a poison value.
  %poison5 = load i64, ptr @g          ; Returns a poison value.

  %cmp = icmp slt i32 %poison, 0       ; Returns a poison value.
  br i1 %cmp, label %end, label %end   ; undefined behavior

end:

適切に定義された値

プログラムの実行において、値にundefビットがなく、実行中にpoisonでない場合、その値は適切に定義されます。集約値またはベクトルの要素が適切に定義されている場合、その集約値またはベクトルは適切に定義されます。集約のパディングは、メモリに格納して異なる型でロードしない限り表示されないため、考慮されません。

単一値の非ベクトル型の定数は、'undef' 定数でも 'poison' 定数でもない場合、適切に定義されます。freeze命令の結果は、オペランドに関係なく適切に定義されます。

基本ブロックのアドレス

blockaddress(@function, %block)

'blockaddress' 定数は、指定された関数内の指定された基本ブロックのアドレスを計算します。

これは常に ptr addrspace(P) 型を持ち、ここで P%block を含む関数のアドレス空間(通常は addrspace(0))です。

エントリブロックのアドレスを取得することは違法です。

この値は、'indirectbr' のオペランドとして使用される場合、または null との比較でのみ定義された動作をします。ラベルアドレス間のポインタ等価性テストは未定義の動作になります。ただし、null との比較は問題なく、null ポインタに等しいラベルはありません。これは、ビットが検査されない限り、不透明なポインタサイズの値として渡すことができます。これにより、indirectbr 命令の前に元の値が再構成される限り、これらの値に対して ptrtoint および算術演算を実行できます。

最後に、一部のターゲットでは、値をインラインアセンブリのオペランドとして使用する場合に定義されたセマンティクスを提供する場合がありますが、それはターゲット固有です。

DSOローカル相当

dso_local_equivalent @func

'dso_local_equivalent' 定数は、与えられた関数と機能的に同等であるが、常に現在のリンケージユニットで定義されている関数を表します。結果のポインタは、基になる関数と同じ型を持ちます。結果のポインタは、関数のポインタと異なることが許可されていますが、必須ではなく、異なる翻訳単位で異なる値を持つ可能性があります。

ターゲット関数は extern_weak リンケージを持つことはできません。

dso_local_equivalent は次のように実装できます。

  • 関数がローカルリンケージ、隠蔽された可視性、または dso_local である場合、dso_local_equivalent は単にその関数へのポインタとして実装できます。

  • dso_local_equivalent は、関数をテール呼び出しするスタブで実装できます。多くのターゲットは、関数がリンケージユニット内で定義されているかどうかに応じて、リンク時に関数またはそのスタブのいずれかに解決される再配置をサポートします。LLVMは、利用可能な場合にこれを使用します。(これは一般に「PLTスタブ」と呼ばれます。)他のターゲットでは、スタブを明示的に出力する必要がある場合があります。

これは、元の関数を明示的に dso_local にする必要なく、関数の dso_local インスタンスが必要な場所で使用できます。これを使用できるインスタンスの1つは、関数と他の dso_local シンボル間の静的オフセット計算です。これは、VTables内の関数ポインタの動的な再配置を、dso_local でない可能性のあるVTableと仮想関数間のオフセットの静的な再配置に置き換えることができる相対的なVTables C++ ABIに特に役立ちます。

これは現在、ELFバイナリ形式でのみサポートされています。

CFIなし

no_cfi @func

制御フロー整合性(CFI)を使用すると、'no_cfi' 定数は、LowerTypeTests パスでCFIジャンプテーブルへの参照に置き換えられない関数参照を表します。これらの定数は、実際の関数本体を参照する必要があるオペレーティングシステムカーネルなどの低レベルプログラムで役立つ場合があります。

ポインタ認証定数

ptrauth (ptr CST, i32 KEY[, i64 DISC[, ptr ADDRDISC]?]?)

'ptrauth' 定数は、ポインタ認証ドキュメントで説明されているように、暗号化認証署名がいくつかのビットに埋め込まれたポインタを表します。

'ptrauth' 定数は、必要に応じて判別子 llvm.ptrauth.blend によって供給される可能性がある、llvm.ptrauth.sign 組み込み関数と同等の単なる定数です。

その型は最初の引数と同じです。整数定数判別子とアドレス判別子はオプションで指定できます。それ以外の場合、それらは i64 0 および ptr null の値を持ちます。

アドレス判別子が null の場合、式は次と同等です。

%tmp = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr CST to i64), i32 KEY, i64 DISC)
%val = inttoptr i64 %tmp to ptr

それ以外の場合、式は次と同等です。

%tmp1 = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr ADDRDISC to i64), i64 DISC)
%tmp2 = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr CST to i64), i32 KEY, i64 %tmp1)
%val = inttoptr i64 %tmp2 to ptr

定数式

定数式は、他の定数を含む式を定数として使用できるようにするために使用されます。定数式は、任意のファーストクラス型にすることができ、副作用のない任意のLLVM操作(ロードや呼び出しはサポートされていません)を含めることができます。以下は、定数式の構文です。

trunc (CST to TYPE)

定数に対してtrunc演算を実行します。

ptrtoint (CST to TYPE)

定数に対してptrtoint演算を実行します。

inttoptr (CST to TYPE)

定数に対してinttoptr演算を実行します。これは非常に危険です!

bitcast (CST to TYPE)

定数CSTを別のTYPEに変換します。オペランドの制約は、bitcast命令の制約と同じです。

addrspacecast (CST to TYPE)

定数ポインタまたは定数ポインタベクトルCSTを、別のアドレス空間の別のTYPEに変換します。オペランドの制約は、addrspacecast命令の制約と同じです。

getelementptr (TY, CSTPTR, IDX0, IDX1, ...), getelementptr inbounds (TY, CSTPTR, IDX0, IDX1, ...)

定数に対してgetelementptr演算を実行します。getelementptr命令と同様に、インデックスリストには、"TYへのポインタ"の型に対して意味をなす必要がある1つ以上のインデックスを含めることができます。これらのインデックスは、CSTPTRのアドレス空間のインデックスサイズに合わせて暗黙的に符号拡張または切り捨てられる場合があります。

extractelement (VAL, IDX)

定数に対してextractelement演算を実行します。

insertelement (VAL, ELT, IDX)

定数に対してinsertelement演算を実行します。

shufflevector (VEC1, VEC2, IDXMASK)

定数に対してshufflevector演算を実行します。

add (LHS, RHS)

定数に対する加算を実行します。

sub (LHS, RHS)

定数に対する減算を実行します。

mul (LHS, RHS)

定数に対する乗算を実行します。

shl (LHS, RHS)

定数に対する左シフトを実行します。

xor (LHS, RHS)

定数に対してビット単位のxorを実行します。

その他の値

インラインアセンブラ式

LLVMは、特別な値を使用することで、インラインアセンブラ式(モジュールレベルのインラインアセンブリとは対照的)をサポートします。この値は、インラインアセンブラをテンプレート文字列(出力する命令を含む)、オペランド制約のリスト(文字列として格納)、インラインasm式に副作用があるかどうかを示すフラグ、およびasmを含む関数がそのスタックを保守的に整列させる必要があるかどうかを示すフラグとして表します。

テンプレート文字列は、制約文字列で指定された、指定されたレジスタ/メモリロケーションの置換を示すために、数字が続く「$」を使用して、オペランドの引数置換をサポートします。「${NUM:MODIFIER}」も使用できます。ここで、MODIFIER はオペランドの印刷方法に関するターゲット固有のアノテーションです(Asmテンプレート引数修飾子を参照)。

テンプレート内でリテラルの「$」を含めるには、「$$」を使用します。他の特殊文字を出力に含めるには、他の文字列と同様に、通常の「\XX」エスケープを使用できます。テンプレート置換後、結果のアセンブリ文字列は、無効にしない限り、.s ファイルを出力する場合でも、LLVM の統合アセンブラによって解析されるため、LLVM が認識するアセンブリ構文を含んでいる必要があることに注意してください。

LLVM は、インラインアセンブリの記述に役立ついくつかの追加の置換もサポートしています。

  • ${:uid}: このインラインアセンブリブロブに固有の10進整数に展開されます。この置換は、ローカルラベルを宣言するときに役立ちます。インライン化など、多くの標準的なコンパイラ最適化では、インライン asm ブロブが複製される場合があります。ブロブ固有の識別子を追加することで、2つのラベルがアセンブリ中に競合しないようにします。これは、GCC の %= 特殊フォーマット文字列 を実装するために使用されます。

  • ${:comment}: 現在のターゲットのアセンブリ方言のコメント文字に展開されます。これは通常 # ですが、多くのターゲットは ;//、または ! などの他の文字列を使用します。

  • ${:private}: アセンブラのプライベートラベルプレフィックスに展開されます。このプレフィックスが付いたラベルは、アセンブルされたオブジェクトのシンボルテーブルには表示されません。通常、プレフィックスは L ですが、ターゲットによっては他の文字列を使用する場合があります。.L は比較的よく使われます。

LLVM のインライン asm のサポートは、Clang の GCC 互換インライン asm サポートの要件に基づいてモデル化されています。したがって、ここでリストされている機能セットと制約および修飾子コードは、GCC のインライン asm サポートのものと同様または同一です。ただし、明確にするために、ここで説明するテンプレートおよび制約文字列の構文は、GCC および Clang で受け入れられる構文と同じではありません。また、ほとんどの制約文字は Clang によってそのままパスされますが、C ソースから LLVM アセンブリに変換する際に、一部が他のコードに変換されます。

インラインアセンブラ式の例は次のとおりです。

i32 (i32) asm "bswap $0", "=r,r"

インラインアセンブラ式は、call または invoke 命令の被呼び出し側オペランドとしてのみ使用できます。したがって、通常は次のようになります。

%X = call i32 asm "bswap $0", "=r,r"(i32 %Y)

制約リストに表示されない副作用があるインライン asm は、副作用があるとマークする必要があります。これは、「sideeffect」キーワードを使用することで行われます。例:

call void asm sideeffect "eieio", ""()

場合によっては、インライン asm には、x86 での呼び出しや SSE 命令など、スタックが何らかの方法でアラインされていないと機能しないコードが含まれる場合があります。しかし、asm 内でそのアラインメントを行うコードは含まれていません。コンパイラは、asm に含まれている可能性のあるものについて控えめな仮定を行い、「alignstack」キーワードが存在する場合は、プロローグで通常のスタックアラインメントコードを生成する必要があります。

call void asm alignstack "eieio", ""()

インライン asm は、非標準のアセンブリ方言の使用もサポートしています。想定される方言は ATT です。「inteldialect」キーワードが存在する場合、インライン asm は Intel 方言を使用しています。現在、ATT と Intel のみがサポートされている方言です。例を挙げます。

call void asm inteldialect "eieio", ""()

インライン asm がスタックをアンワインドする可能性がある場合は、コンパイラがアンワインド情報を出力するように、「unwind」キーワードを使用する必要があります。

call void asm unwind "call func", ""()

インライン asm がスタックをアンワインドし、「unwind」キーワードでマークされていない場合、動作は未定義です。

複数のキーワードが表示される場合、「sideeffect」キーワードが最初、「alignstack」キーワードが2番目、「inteldialect」キーワードが3番目、「unwind」キーワードが最後に来る必要があります。

インライン Asm 制約文字列

制約リストは、コンマで区切られた文字列であり、各要素には1つ以上の制約コードが含まれています。

制約リストの各要素について、適切なレジスタまたはメモリオペランドが選択され、リストの最初の制約に対して $0、2番目の制約に対して $1 などとして、アセンブリテンプレート文字列の展開で利用できるようになります。

制約には、出力、入力、クローバーの3つの異なるタイプがあり、制約コードの前のプレフィックス記号で区別されます。制約は常に、出力が最初、次に入力、最後にクローバーという順序で指定する必要があります。それらを混在させることはできません。

制約コードには、さらに3つの異なるカテゴリがあります。

  • レジスタ制約。これは、レジスタクラスまたは固定の物理レジスタです。この種の制約は、レジスタを割り当て、必要に応じて、引数または結果を適切な型にビットキャストします。

  • メモリ制約。この種の制約は、メモリオペランドを取る命令で使用するためのものです。異なる制約により、ターゲットで使用される異なるアドレス指定モードが可能になります。

  • 即値制約。この種の制約は、命令に直接レンダリングできる整数またはその他の即値に使用するためのものです。さまざまなターゲット固有の制約により、使用する命令に適した範囲で値を選択できます。

出力制約

出力制約は、「=」プレフィックス(例:「=r」)で指定されます。これは、アセンブリがこのオペランドに書き込み、オペランドが asm 式の戻り値として利用可能になることを示します。出力制約は、call 命令から引数を消費しません。(ただし、間接出力については下記参照)

通常、すべて入力が読み込まれるまで、アセンブリ式によって出力場所に書き込みが行われないことが想定されています。そのため、LLVM は出力と入力に同じレジスタを割り当てる場合があります。これが安全でない場合(例えば、アセンブリに2つの命令が含まれていて、最初の命令が1つの出力に書き込み、2番目の命令が入力を読み取って2番目の出力に書き込む場合)、出力が「early-clobber」出力であることを指定するために、「&」修飾子(例:「=&r」)を使用する必要があります。出力を「early-clobber」としてマークすると、LLVM が(この出力に結び付けられた入力を除く)入力に同じレジスタを使用しないことが保証されます。

入力制約

入力制約にはプレフィックスがなく、制約コードのみです。各入力制約は、call 命令から1つの引数を消費します。asm が入力レジスタまたはメモリロケーションに書き込むことは許可されていません(その入力が出力に結び付けられている場合を除く)。また、LLVM がそれらすべてが必ず同じ値を含んでいると判断できる場合、複数の入力をすべて同じレジスタに割り当てることができます。

制約コードを提供する代わりに、入力制約は、制約文字列として整数を提供することにより、出力制約に「結び付ける」こともできます。結び付けられた入力は、依然として call 命令から引数を消費し、通常どおり asm テンプレート番号の位置を占めます。つまり、結び付けられた出力と同じレジスタを常に使用するように制約されます。例えば、「=r,0」の制約文字列は、出力用にレジスタを割り当て、そのレジスタを入力としても使用するように(0番目の制約である)指示します。

入力と「early-clobber」出力を結び付けることが許可されています。その場合、early-clobber に結び付けられた入力と同じレジスタを、他の入力が共有することはできません(他の入力が同じ値を持っている場合でも)。

入力は、メモリ制約ではなく、レジスタ制約を持つ出力にのみ結び付けることができます。出力に結び付けることができる入力は1つだけです。

また、少し説明に値する「興味深い」機能もあります。レジスタクラス制約が、入力として提供された値型オペランドに対して小さすぎるレジスタを割り当てた場合、入力値は複数のレジスタに分割され、それらすべてがインライン asm に渡されます。

ただし、この機能は、あなたが思うほど便利ではないことがよくあります。

まず、レジスタが連続していることは保証されていません。そのため、複数の連続した命令で動作する命令を持つアーキテクチャでは、これはそれらをサポートする適切な方法ではありません。(例えば、32ビットのSparcV8には、単一の32ビットレジスタを取る64ビットのロードがあります。ハードウェアは、指定されたレジスタと次のレジスタの両方にロードします。インライン asm のこの機能は、それをサポートするのに役立ちません。)

いくつかのターゲットは、2レジスタオペランドの2番目のレジスタへの明示的なアクセスを可能にするテンプレート文字列修飾子(例えば、MIPS LM、および D)を提供します。そのようなアーキテクチャでは、実際に割り当てられた2番目のレジスタにアクセスできます(それでも、後続のレジスタにはアクセスできません)。しかし、その場合でも、わかりやすくするために、値を2つの別々のオペランドに分割する方がおそらく良いでしょう。(例えば、この機能でのみ使用するために存在するにもかかわらず、使用することはあまり推奨されない、X86 の A 制約の説明を参照してください。)

間接入力と出力

間接的な出力制約または入力制約は、"*" 修飾子(出力の場合は "=" の後につきます)で指定できます。これは、asm が入力引数として提供されたアドレスの内容を書き込みまたは読み取ることを示します。(この方法では、間接的な出力は出力というよりは入力のように動作することに注意してください。入力と同様に、戻り値を生成するのではなく、呼び出し式の引数を消費します。間接的な出力制約は、asm が入力メモリ位置の内容を読み取るだけでなく、書き込むことが期待されるという点で「出力」にすぎません。)

これは最も一般的には、変数のアドレスを値として渡すために、メモリ制約(例えば、"=*m")に使用されます。

間接的なレジスタ制約を使用することも可能ですが、出力に対してのみです(例えば、"=*r")。これにより、LLVM は通常、出力値にレジスタを割り当て、その後、提供されたインライン asm の後に、入力として提供されたアドレスへのストアを別途発行します。(この機能がどのような価値を提供するかは不明確です。asm ステートメントの後に明示的にストアを記述するのと比較して、多くの最適化パスをバイパスするため、コードが悪化する可能性があります。使用しないことをお勧めします。)

間接制約の呼び出し引数はポインタ型を持ち、ポインタの要素型を示す elementtype 属性を指定する必要があります。

クロバー制約

クロバー制約は、"~" 接頭辞で示されます。クロバーは、入力オペランドを消費することも、出力を生成することもありません。クロバーは、一般的な制約コード文字を使用することはできません。明示的なレジスタ制約のみを使用できます(例えば、"~{eax}")。唯一の例外は、"~{memory}" のクロバー文字列は、宣言された間接出力によって指し示されるメモリだけでなく、任意の未宣言メモリ位置にアセンブリが書き込むことを示すことです。

出力制約にも存在する名前付きレジスタをクロバーすることは違法であることに注意してください。

ラベル制約

ラベル制約は、"!" 接頭辞で示され、通常は "!i" の形式で使用されます。ラベル制約は、呼び出し引数を消費する代わりに、callbr 命令の間接的な宛先ラベルを消費します。

ラベル制約は、callbr と組み合わせてのみ使用でき、ラベル制約の数は callbr 命令の間接的な宛先ラベルの数と一致する必要があります。

制約コード

潜在的な接頭辞の後には、制約コード、または複数のコードが続きます。

制約コードは、単一の文字(例えば、"r")、"^" 文字の後に 2 文字(例えば、"^wc")、または "{" レジスタ名 "}" (例えば、"{eax}")のいずれかです。

1 文字および 2 文字の制約コードは、通常、GCC の制約コードと同じになるように選択されています。

単一の制約には、1 つ以上の制約コードを含めることができ、どれを使用するかは LLVM に委ねられます。これは主に、clang からの GCC インライン asm の翻訳との互換性のために含まれています。

代替案を指定する方法は 2 つあり、どちらかまたは両方をインライン asm 制約リストで使用できます。

  1. コードを互いに付加して、制約コードセットを作成します。例えば、"im" や "{eax}m" です。これは、「セット内のいずれかのオプションを選択する」ことを意味します。制約の選択は、制約リスト内の各制約に対して独立して行われます。

  2. 制約コードセットの間に "|" を使用して、代替案を作成します。制約リスト内のすべての制約は、同じ数の代替セットを持つ必要があります。この構文では、制約リスト内のすべての項目の同じ代替案が一緒に選択されます。

これらを組み合わせると、例えば、"rm|r,ri|rm" のような 2 つのオペランド制約文字列を使用できます。これは、オペランド 0 が r または m の場合、オペランド 1 は r または i のいずれかである可能性があることを示します。オペランド 0 が r の場合、オペランド 1 は r または m のいずれかである可能性があります。ただし、オペランド 0 と 1 の両方を m 型にすることはできません。

ただし、LLVM はどちらを使用するかについてインテリジェントな選択をすることができないため、代替機能のいずれかの使用は推奨されません。(現在選択する必要がある時点で、スマートな方法で選択するための十分な情報が得られません。)したがって、最適なパフォーマンスになるものではなく、コンパイルされる可能性が最も高い選択を試みるだけです。(例えば、"rm" が与えられた場合、レジスタではなく常にメモリを使用することを選択します。)また、複数のレジスタまたは複数のレジスタクラスが与えられた場合は、最初のものを選択します。(実際には、明示的に指定された物理レジスタが一意であることを現在保証すらしていないため、{r11}{r12},{r11}{r12} のように複数の物理レジスタを代替として指定すると、意図したとおりではなく、両方のオペランドに r11 が割り当てられます。)

サポートされている制約コードリスト

制約コードは、一般的に、GCC での動作と同じように動作することが期待されます。LLVM のサポートは、GCC でサポートされていた C インライン asm コードをサポートするために、「必要に応じて」実装されることがよくあります。LLVM と GCC の間で動作の不一致がある場合は、LLVM にバグがある可能性が高いことを示します。

一部の制約コードは、通常、すべてのターゲットでサポートされています

  • r:ターゲットの汎用レジスタクラスのレジスタ。

  • m:メモリアドレスオペランド。サポートされているアドレッシングモードはターゲット固有であり、一般的な例はレジスタ、またはレジスタ + レジスタオフセット、またはレジスタ + 即値オフセット(ターゲット固有のサイズ)です。

  • p:アドレスオペランド。m に似ていますが、メモリに触れることなく「ロードアドレス」タイプの命令で使用されます。

  • i:整数定数(ターゲット固有の幅)。単純な即値またはリロケータブル値を許可します。

  • n:整数定数 - リロケータブル値は含みません

  • s:定数オフセット付きのシンボルまたはラベル参照。

  • X:制約なしで、任意の種類のオペランドを許可します。通常、asm ブランチまたは呼び出しのラベルを渡すのに便利です。

  • {register-name}:指定された物理レジスタを正確に要求します。

その他の制約はターゲット固有です

AArch64

  • z:即値整数 0。必要に応じて WZR または XZR を出力します。

  • IADD または SUB 命令に有効な即値整数。つまり、0 から 4095 までの値で、オプションで 12 シフトできます。

  • J:否定された場合に ADD または SUB 命令に有効な即値整数。つまり、-1 から -4095 までの値で、オプションで左に 12 シフトできます。

  • K:32 ビットレジスタを使用した ANDEOR、または ORR のような論理命令の「ビットマスク即値 32」に有効な即値整数。

  • L:64 ビットレジスタを使用した ANDEOR、または ORR のような論理命令の「ビットマスク即値 64」に有効な即値整数。

  • M:32 ビットレジスタでの MOV アセンブリエイリアスで使用するための即値整数。これは K のスーパーセットです。ビットマスク即値に加えて、単一の MOVZ または MOVL 命令でロードできる即値整数も許可します。

  • N:64 ビットレジスタでの MOV アセンブリエイリアスで使用するための即値整数。これは L のスーパーセットです。

  • Q:メモリアドレスオペランドは、単一のレジスタ(オフセットなし)である必要があります。(ただし、LLVM は現在、m 制約についてもこれを行っています。)

  • r:32 ビットまたは 64 ビットの整数レジスタ(W* または X*)。

  • S:定数オフセット付きのシンボルまたはラベル参照。一般的な s はサポートされていません。

  • Uci:r と同様ですが、レジスタ 8 から 11(両端を含む)に制限されています。

  • Ucj:r と同様ですが、レジスタ 12 から 15(両端を含む)に制限されています。

  • w:32 ビット、64 ビット、または 128 ビットの浮動小数点、SIMD または SVE ベクトルレジスタ。

  • x:w と同様ですが、レジスタ 0 から 15(両端を含む)に制限されています。

  • y: w と同様ですが、SVE ベクトルレジスタ Z0 から Z7 (両端を含む) に限定されます。

  • Uph: 上位 8 つの SVE 述語レジスタ (P8 から P15) のいずれか。

  • Upl: 下位 8 つの SVE 述語レジスタ (P0 から P7) のいずれか。

  • Upa: すべての SVE 述語レジスタ (P0 から P15) のいずれか。

AMDGPU

  • r: 32 ビットまたは 64 ビットの整数レジスタ。

  • [0-9]v: 32 ビットの VGPR レジスタ、番号 0 から 9。

  • [0-9]s: 32 ビットの SGPR レジスタ、番号 0 から 9。

  • [0-9]a: 32 ビットの AGPR レジスタ、番号 0 から 9。

  • I: -16 から 64 の範囲の整数インライン定数。

  • J: 16 ビットの符号付き整数定数。

  • A: 整数または浮動小数点インライン定数。

  • B: 32 ビットの符号付き整数定数。

  • C: 32 ビットの符号なし整数定数、または -16 から 64 の範囲の整数インライン定数。

  • DA: 2 つの "A" 定数に分割できる 64 ビット定数。

  • DB: 2 つの "B" 定数に分割できる 64 ビット定数。

すべての ARM モード

  • Q, Um, Un, Uq, Us, Ut, Uv, Uy: メモリアドレスオペランド。現時点ではオペランド m と同じように扱われます。

  • Te: 偶数の汎用 32 ビット整数レジスタ: r0,r2,...,r12,r14

  • To: 奇数の汎用 32 ビット整数レジスタ: r1,r3,...,r11

ARM および ARM の Thumb2 モード

  • j: 0 から 65535 の間の即値整数 ( MOVW に有効)

  • I: データ処理命令に有効な即値整数。

  • J: -4095 から 4095 の間の即値整数。

  • K: ビット単位反転がデータ処理命令に有効な即値整数。(テンプレート修飾子 "B" で反転した値を表示できます)。

  • L: 否定がデータ処理命令に有効な即値整数。(テンプレート修飾子 "n" で否定された値を表示できます)。

  • M: 2 のべき乗または 0 から 32 の間の整数。

  • N: 無効な即値制約。

  • O: 無効な即値制約。

  • r: 汎用 32 ビット整数レジスタ ( r0-r15)。

  • l: Thumb2 モードでは、下位 32 ビットの GPR レジスタ ( r0-r7)。ARM モードでは、 r と同じ。

  • h: Thumb2 モードでは、上位 32 ビットの GPR レジスタ ( r8-r15)。ARM モードでは無効。

  • w: それぞれ s0-s31, d0-d31, または q0-q15 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

  • t: それぞれ s0-s31, d0-d15, または q0-q7 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

  • x: それぞれ s0-s15, d0-d7, または q0-q3 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

ARM の Thumb1 モード

  • I: 0 から 255 の間の即値整数。

  • J: -255 から -1 の間の即値整数。

  • K: 0 から 255 の間の即値整数。オプションでいくつかの量だけ左シフトします。

  • L: -7 から 7 の間の即値整数。

  • M: 0 から 1020 の間の 4 の倍数である即値整数。

  • N: 0 から 31 の間の即値整数。

  • O: -508 から 508 の間の 4 の倍数である即値整数。

  • r: 下位 32 ビットの GPR レジスタ ( r0-r7)。

  • l: 下位 32 ビットの GPR レジスタ ( r0-r7)。

  • h: 上位 GPR レジスタ ( r0-r7)。

  • w: それぞれ s0-s31, d0-d31, または q0-q15 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

  • t: それぞれ s0-s31, d0-d15, または q0-q7 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

  • x: それぞれ s0-s15, d0-d7, または q0-q3 の範囲の 32, 64, または 128 ビットの浮動小数点/SIMD レジスタ。

Hexagon

  • o, v: メモリアドレスオペランド。現時点では制約 m と同じように扱われます。

  • r: 32 ビットまたは 64 ビットのレジスタ。

LoongArch

  • f: 浮動小数点レジスタ (利用可能な場合)。

  • k: ベースレジスタと (オプションでスケールされた) インデックスレジスタによってアドレスが形成されるメモリオペランド。

  • l: 符号付き 16 ビット定数。

  • m: ベースレジスタと、st.w および ld.w と同じアドレッシングモードの命令で使用するのに適したオフセットによってアドレスが形成されるメモリオペランド。

  • I: 符号付き 12 ビット定数 (算術命令用)。

  • J: 即値整数ゼロ。

  • K: 符号なし 12 ビット定数 (論理命令用)。

  • ZB: 汎用レジスタに保持されているアドレス。オフセットはゼロです。

  • ZC: ベースレジスタと、ll.w および sc.w と同じアドレッシングモードの命令で使用するのに適したオフセットによってアドレスが形成されるメモリオペランド。

MSP430

  • r: 8 ビットまたは 16 ビットのレジスタ。

MIPS

  • I: 即値符号付き 16 ビット整数。

  • J: 即値整数ゼロ。

  • K: 即値符号なし 16 ビット整数。

  • L: 下位 16 ビットが 0 である即値 32 ビット整数。

  • N: -65535 から -1 の間の即値整数。

  • O: 即値符号付き 15 ビット整数。

  • P: 1 から 65535 の間の即値整数。

  • m: メモリアドレスオペランド。MIPS-SE モードでは、ベースアドレスレジスタに加えて 16 ビットの即値オフセットを使用できます。MIPS モードでは、ベースレジスタのみです。

  • R: メモリアドレスオペランド。MIPS-SE モードでは、ベースアドレスレジスタに加えて 9 ビットの符号付きオフセットを使用できます。MIPS モードでは、制約 m と同じ。

  • ZC: 特定のサブターゲット上の pref, ll, または sc 命令での使用に適したメモリアドレスオペランド (詳細は異なります)。

  • r, d, y: 32 ビットまたは 64 ビットの GPR レジスタ。

  • f: 32 ビットまたは 64 ビットの FPU レジスタ ( F0-F31)、または 128 ビットの MSA レジスタ ( W0-W31)。MSA レジスタの場合、GCC との互換性のために w 引数修飾子を使用することをお勧めします。

  • c: 間接ジャンプに適した 32 ビットまたは 64 ビットの GPR レジスタ (常に 25)。

  • l: lo レジスタ、32 ビットまたは 64 ビット。

  • x: 無効。

NVPTX

  • b: 1 ビットの整数レジスタ。

  • c または h: 16 ビットの整数レジスタ。

  • r: 32 ビットの整数レジスタ。

  • l または N: 64 ビットの整数レジスタ。

  • q: 128 ビットの整数レジスタ。

  • f: 32 ビットの浮動小数点レジスタ。

  • d: 64 ビットの浮動小数点レジスタ。

PowerPC

  • I: 即値符号付き 16 ビット整数。

  • J: 左に 16 ビットシフトされた即値符号なし 16 ビット整数。

  • K: 即値符号なし 16 ビット整数。

  • L: 左に 16 ビットシフトされた即値符号付き 16 ビット整数。

  • M: 31 より大きい即値整数。

  • N: 2 のべき乗である即値整数。

  • O: 即値整数定数 0。

  • P: 否定が符号付き 16 ビット定数である即値整数定数。

  • es, o, Q, Z, Zy: メモリアドレスオペランド。現在は m と同じように扱われます。

  • r: 32 ビットまたは 64 ビットの整数レジスタ。

  • b: 32ビットまたは64ビットの整数レジスタ。ただし、R0 は除きます(つまり、R1-R31)。

  • f: 32ビットまたは64ビットの浮動小数点レジスタ (F0-F31)。

  • v: 4 x f32 または 4 x f64 型の場合、128ビットの AltiVec ベクトルレジスタ

    レジスタ (V0-V31)。

  • y: 条件レジスタ (CR0-CR7)。

  • wc: CRレジスタ内の個別のCRビット。

  • wa, wd, wf: 完全なVSXレジスタセット(浮動小数点レジスタファイルとベクトルレジスタファイルの両方をオーバーラップ)の任意の128ビットVSXベクトルレジスタ。

  • ws: 完全なVSXレジスタセットの32ビットまたは64ビットの浮動小数点レジスタ。

RISC-V

  • A: アドレスオペランド(オフセットなしで汎用レジスタを使用)。

  • I: 12ビットの符号付き整数イミディエートオペランド。

  • J: ゼロ整数イミディエートオペランド。

  • K: 5ビットの符号なし整数イミディエートオペランド。

  • f: 32ビットまたは64ビットの浮動小数点レジスタ (FまたはD拡張が必要)。

  • r: 32ビットまたは64ビットの汎用レジスタ(プラットフォームの XLEN に依存)。

  • S: s のエイリアス。

  • vr: ベクトルレジスタ。(V拡張が必要)。

  • vm: マスクオペランド用のベクトルレジスタ。(V拡張が必要)。

Sparc

  • I: 13ビットの符号付き整数イミディエート。

  • r: 32 ビットの整数レジスタ。

  • f: SparcV8の任意の浮動小数点レジスタ、またはSparcV9のレジスタの「下位」半分にある浮動小数点レジスタ。

  • e: 任意の浮動小数点レジスタ。(SparcV8では f と同じ)。

SystemZ

  • I: 符号なし8ビット整数イミディエート。

  • J: 符号なし12ビット整数イミディエート。

  • K: 符号付き16ビット整数イミディエート。

  • L: 符号付き20ビット整数イミディエート。

  • M: イミディエート整数 0x7fffffff。

  • Q: ベースアドレスと12ビットの符号なしイミディエート変位を持つメモリアドレスオペランド。

  • R: ベースアドレス、12ビットの符号なしイミディエート変位、およびインデックスレジスタを持つメモリアドレスオペランド。

  • S: ベースアドレスと20ビットの符号付きイミディエート変位を持つメモリアドレスオペランド。

  • T: ベースアドレス、20ビットの符号付きイミディエート変位、およびインデックスレジスタを持つメモリアドレスオペランド。

  • r または d: 32、64、または128ビットの整数レジスタ。

  • a: 32、64、または128ビットの整数アドレスレジスタ (アドレスコンテキストではゼロとして評価される R0 は除く)。

  • h: 64ビットデータレジスタの上位部にある32ビット値 (LLVM固有)。

  • f: 32、64、または128ビットの浮動小数点レジスタ。

X86

  • I: 0 から 31 の間のイミディエート整数。

  • J: 0 から 64 の間のイミディエート整数。

  • K: 符号付き8ビット整数イミディエート。

  • L: イミディエート整数、0xff または 0xffff または(64ビットモードでのみ)0xffffffff。

  • M: 0 から 3 の間のイミディエート整数。

  • N: 符号なし8ビット整数イミディエート。

  • O: 0 から 127 の間のイミディエート整数。

  • e: 符号付き32ビット整数イミディエート。

  • Z: 符号なし32ビット整数イミディエート。

  • q: 8ビットの l 整数レジスタとしてアクセスできる8、16、32、または64ビットのレジスタ。X86-32では、これは a, b, c, および d レジスタであり、X86-64では、すべての整数レジスタです。機能 egprinline-asm-use-gpr32 の両方がオンの場合、gpr32 に拡張されます。

  • Q: 8ビットの h 整数レジスタとしてアクセスできる8、16、32、または64ビットのレジスタ。これは a, b, c, および d レジスタです。

  • r または l: 8、16、32、または64ビットの整数レジスタ。機能 egprinline-asm-use-gpr32 の両方がオンの場合、gpr32 に拡張されます。

  • R: i386から存在し、REXプレフィックスなしでアクセスできる8、16、32、または64ビットの「レガシー」整数レジスタ。

  • f: 32、64、または80ビットの ‘387 FPUスタック擬似レジスタ。

  • y: MMXが有効になっている場合、64ビットのMMXレジスタ。

  • v: SSEが有効になっている場合:SSEレジスタ内の32ビットまたは64ビットのスカラーオペランド、または128ビットのベクトルオペランド。AVXも有効になっている場合、AVXレジスタ内の256ビットのベクトルオペランドも可能です。AVX-512も有効になっている場合、AVX512レジスタ内の512ビットのベクトルオペランドも可能です。それ以外の場合はエラー。

  • Ws: オプションの定数加算またはラベル参照を持つシンボリック参照。

  • x: v と同じですが、AVX-512が有効になっている場合、x コードは最初の16個のAVX-512レジスタにのみ割り当てられますが、v コードは32個のAVX-512レジスタのいずれにも割り当てられます。

  • Y: SSE2 が有効になっている場合は x と同じ。それ以外の場合はエラー。

  • A: 特殊なケース:単一のオペランドの場合、最初にEAX、次にEDXを割り当てます(32ビットモードでは、64ビット整数オペランドは2つのレジスタに分割されます)。64ビットモードでは、64ビットオペランドはRAXにのみ割り当てられるため、この制約を使用することはお勧めできません。2つの32ビットオペランドが必要な場合は、asmステートメントに渡す前に自分で分割することをお勧めします。

  • jr: 8、16、32、または64ビットの整数gpr16。機能 egpr または inline-asm-use-gpr32 がオンの場合でも、gpr32 に拡張されることはありません。

  • jR: 機能 egpr がオンの場合、8、16、32、または64ビットの整数 gpr32。それ以外の場合は、r と同じ。

XCore

  • r: 32 ビットの整数レジスタ。

アセンブリテンプレート引数修飾子

アセンブリテンプレート文字列では、オペランド参照に “${0:n}” のような修飾子を使用できます。

一般に、修飾子はGCCと同じように動作すると予想されます。LLVMのサポートは、GCCでサポートされていたCインラインアセンブリコードをサポートするために、「必要に応じて」実装されることがよくあります。LLVMとGCCの動作の不一致は、LLVMのバグを示している可能性があります。

ターゲット非依存

  • c: ターゲット固有のイミディエート句読点なしで(例:$プレフィックスなし)、即値整数定数をそのまま出力します。

  • n: ターゲット固有のイミディエート句読点なしで(例:$プレフィックスなし)、即値整数定数を否定してそのまま出力します。

  • l: ターゲット固有のラベル句読点なしで(例:$プレフィックスなし)、ラベルをそのまま出力します。

AArch64

  • w: x* 名の代わりに w* 名でGPRレジスタを出力します。例:x30 の代わりに、w30 を出力します。

  • x: x* 名でGPRレジスタを出力します。(これはデフォルトでもあります)。

  • b, h, s, d, q: デフォルトの v* ではなく、b*, h*, s*, d*, または q* 名で浮動小数点/SIMDレジスタを出力します。

AMDGPU

  • r: 効果なし。

ARM

  • a: オペランドをアドレスとして(レジスタを [] で囲んで)出力します。

  • P: 効果はありません。

  • q: 効果はありません。

  • y: VFP 単精度レジスタをインデックス付き倍精度として出力します(例:s9 の代わりに d4[1] として出力します)。

  • B: 即値整数定数をビット反転し、# 接頭辞なしで出力します。

  • L: 即値整数定数の下位 16 ビットを出力します。

  • M: ldm/stm に適したレジスタセットとして出力します。指定されたオペランドに続くすべてのレジスタオペランドも出力するため、注意して使用してください。

  • Q: レジスタペアの下位レジスタ、または 2 レジスタオペランドの下位レジスタを出力します。

  • R: レジスタペアの上位レジスタ、または 2 レジスタオペランドの上位レジスタを出力します。

  • H: レジスタペアの 2 番目のレジスタを出力します。(ビッグエンディアンシステムでは、HQ と同等であり、リトルエンディアンシステムでは HR と同等です。)

  • e: NEON クワッドレジスタの下位ダブルワードレジスタを出力します。

  • f: NEON クワッドレジスタの上位ダブルワードレジスタを出力します。

  • m: メモリオペランドのベースレジスタを [] の装飾なしで出力します。

Hexagon

  • L: 2 レジスタオペランドの 2 番目のレジスタを出力します。最初に連続して割り当てられている必要があります。

  • I: オペランドが整数定数の場合、文字 'i' を出力し、そうでない場合は何も出力しません。 'addi' 命令と 'add' 命令を出力するために使用されます。

LoongArch

  • z: オペランドがゼロの場合、$zero レジスタを出力し、そうでない場合は通常どおり出力します。

MSP430

追加の修飾子はありません。

MIPS

  • X: 即値整数を 16 進数として出力します。

  • x: 即値整数の下位 16 ビットを 16 進数として出力します。

  • d: 即値整数を 10 進数として出力します。

  • m: 1 を減算し、即値整数を 10 進数として出力します。

  • z: 即値ゼロの場合、$0 を出力し、そうでない場合は通常どおり出力します。

  • L: 2 レジスタオペランドの下位レジスタを出力するか、倍精度メモリオペランドの下位ワードのアドレスを出力します。

  • M: 2 レジスタオペランドの上位レジスタを出力するか、倍精度メモリオペランドの上位ワードのアドレスを出力します。

  • D: 2 レジスタオペランドの 2 番目のレジスタを出力するか、倍精度メモリオペランドの 2 番目のワードを出力します。(ビッグエンディアンシステムでは、DL と同等であり、リトルエンディアンシステムでは DM と同等です。)

  • w: 効果はありません。 f 制約付きで MSA レジスタ (W0-W31) を出力するためにこの修飾子を必要とする GCC との互換性のために提供されます。

NVPTX

  • r: 効果なし。

PowerPC

  • L: 2 レジスタオペランドの 2 番目のレジスタを出力します。最初に連続して割り当てられている必要があります。

  • I: オペランドが整数定数の場合、文字 'i' を出力し、そうでない場合は何も出力しません。 'addi' 命令と 'add' 命令を出力するために使用されます。

  • y: メモリオペランドの場合、2 レジスタ X 形式命令のフォーマッタを出力します。(現在、常に r0,OPERAND を出力します)。

  • U: メモリオペランドが更新形式の場合、'u' を出力し、それ以外の場合は何も出力しません。(注:LLVM は更新形式をサポートしていないため、現在は常に何も出力しません)

  • X: メモリオペランドがインデックス形式の場合、'x' を出力します。(注:LLVM はインデックス形式をサポートしていないため、現在は常に何も出力しません)

RISC-V

  • i: オペランドがレジスタでない場合、文字 'i' を出力し、そうでない場合は何も出力しません。 'addi' 命令と 'add' 命令などを出力するために使用されます。

  • z: 即値ゼロの場合、レジスタ zero を出力し、そうでない場合は通常どおり出力します。

Sparc

  • L: 2 レジスタオペランドの下位レジスタを出力します。

  • H: 2 レジスタオペランドの上位レジスタを出力します。

  • r: 効果なし。

SystemZ

SystemZ は n のみを実装し、他のターゲットに依存しない修飾子をサポートしていません

X86

  • c: 装飾されていない整数またはシンボル名を出力します。(後者は、この通常ターゲットに依存しない修飾子のターゲット固有の動作です)。

  • A: レジスタ名の前に「*」を付けて出力します。

  • b: 8 ビットレジスタ名(例:al)を出力します。メモリオペランドでは何もしません。

  • h: 上位 8 ビットレジスタ名(例:ah)を出力します。メモリオペランドでは何もしません。

  • w: 16 ビットレジスタ名(例:ax)を出力します。メモリオペランドでは何もしません。

  • k: 32 ビットレジスタ名(例:eax)を出力します。メモリオペランドでは何もしません。

  • q: 64 ビットレジスタが利用可能な場合は 64 ビットレジスタ名(例:rax)を、それ以外の場合は 32 ビットレジスタ名を出力します。メモリオペランドでは何もしません。

  • n: 装飾されていない整数を否定して出力するか、即値整数以外のオペランド(例:再配置可能なシンボル式)の場合は、オペランドの前に「-」を出力します。(再配置可能なシンボル式の動作は、この通常ターゲットに依存しない修飾子のターゲット固有の動作です)。

  • H: 追加オフセット +8 を持つメモリ参照を出力します。

  • p: 構文固有のプレフィックスなしで、生のシンボル名を出力します。

  • P: call 命令の引数として使用されるか、明示的なベースレジスタとインデックスレジスタをオフセットとして使用されるメモリ参照を出力します。したがって、メモリ参照を提示するために追加のレジスタを使用することはできません。(例:PC 相対であっても (rip) を省略します。)

XCore

追加の修飾子はありません。

インラインアセンブリメタデータ

インラインアセンブリノードをラップする call 命令には、定数整数のリストを含む「!srcloc」MDNode がアタッチされている場合があります。存在する場合、コードジェネレーターは LLVMContext エラー報告メカニズムを通じてエラーを報告する際に、整数をロケーションクッキー値として使用します。これにより、フロントエンドはインラインアセンブリで発生したバックエンドエラーを、それを生成したソースコードに関連付けることができます。例:

call void asm sideeffect "something bad", ""(), !srcloc !42
...
!42 = !{ i64 1234567 }

IR に配置するマジックナンバーの意味を理解するのはフロントエンドの責任です。MDNode に複数の定数が含まれている場合、コードジェネレーターはエラーが発生したアセンブリの行に対応する定数を使用します。

メタデータ

LLVM IR では、コードに関する追加情報をオプティマイザーとコードジェネレーターに伝えることができる、プログラム内の命令とグローバルオブジェクトにメタデータをアタッチできます。

メタデータプリミティブには、文字列とノードの 2 つがあります。また、識別名と名前付き引数のセットを持つ特殊なノードもあります。

注記

メタデータの適用例の 1 つは、ソースレベルのデバッグ情報であり、現在特殊なノードの唯一のユーザーです。

メタデータには型はなく、値ではありません。

metadata 型以外の値は、構文「<type> <value>」を使用してメタデータコンテキストで使用できます。

他のすべてのメタデータは、感嘆符(' !')で始まる構文で識別されます。

メタデータは、metadata 型を使用することで、次の値コンテキストで使用できます。

  • 特定の組み込み関数の引数(仕様に記載のとおり)。

  • catchpad/cleanuppad 命令の引数。

注記

メタデータは、MetadataAsValue で「ラップ」できるため、値コンテキストで参照できます。MetadataAsValueValue です。

型付きの値は、メタデータコンテキストで参照できるように、ValueAsMetadata で「ラップ」することができます。ValueAsMetadataMetadata の一種です。

ValueAsMetadata の明示的な構文はありません。代わりに、型識別子が感嘆符で始まらないという事実が、曖昧さを解消するために使用されます。

metadata 型は MetadataAsValue を意味し、「<type> <value>」ペアが続く場合、型付きの値を ValueAsMetadata でラップします。

たとえば、この呼び出しの最初の引数は MetadataAsValue(ValueAsMetadata(Value)) です。

call void @llvm.foo(metadata i32 1)

一方、この呼び出しの最初の引数は MetadataAsValue(MDNode) です。

call void @llvm.foo(metadata !0)

この MDTuple の最初の要素は MDNode です。

!{!0}

そして、この MDTuple の最初の要素は ValueAsMetadata(Value) です。

!{i32 1}

メタデータ文字列 (MDString)

メタデータ文字列は、二重引用符で囲まれた文字列です。非印刷文字を「\xx」でエスケープすることにより、任意の文字を含めることができます。「xx」は2桁の16進コードです。例:「!"test\00"」。

注記

メタデータ文字列はメタデータですが、メタデータノードではありません。

メタデータノード (MDNode)

メタデータタプルは、構造体定数に似た表記で表されます。つまり、カンマで区切られた要素のリストを、中括弧で囲み、感嘆符で前置します。メタデータノードは、オペランドとして任意の値を持つことができます。例:

!{!"test\00", i32 10}

ユニーク化されていないメタデータノードは、distinct キーワードを使用します。例:

!0 = distinct !{!"test\00", i32 10}

distinct ノードは、ノードがコンテンツに基づいてマージされるべきではない場合に役立ちます。また、メタデータオペランドが変更されたときに、変換によってユニーク化の衝突が発生した場合にも発生する可能性があります。

名前付きメタデータは、モジュールシンボルテーブルで検索できるメタデータノードのコレクションです。例:

!foo = !{!4, !3}

メタデータは、関数引数として使用できます。ここで、llvm.dbg.value 組み込み関数は、3つのメタデータ引数を使用しています。

call void @llvm.dbg.value(metadata !24, metadata !25, metadata !26)

メタデータは命令にアタッチできます。ここで、メタデータ !21 は、!dbg 識別子を使用して、add 命令にアタッチされています。

%indvar.next = add i64 %indvar, 1, !dbg !21

命令は、同じ識別子を持つ複数のメタデータアタッチメントを持つことはできません。

メタデータは、関数またはグローバル変数にもアタッチできます。ここで、メタデータ !22 は、!dbg 識別子を使用して、f1 および f2 関数、およびグローバル変数 g1 および g2 にアタッチされています。

declare !dbg !22 void @f1()
define void @f2() !dbg !22 {
  ret void
}

@g1 = global i32 0, !dbg !22
@g2 = external global i32, !dbg !22

命令とは異なり、グローバルオブジェクト(関数とグローバル変数)は、同じ識別子を持つ複数のメタデータアタッチメントを持つことができます。

変換は、不明なメタデータアタッチメント、または保持できないとわかっているメタデータアタッチメントを削除する必要があります。現在、!func_sanitize!type!absolute_symbol、および !associated のグローバルへのメタデータアタッチメントには例外があり、グローバル自体が削除されない限り、無条件に削除することはできません。

名前付きメタデータを使用してモジュールにアタッチされたメタデータは、デバッグメタデータ(名前が !llvm.dbg.* の名前付きメタデータ)を除き、削除することはできません。

オプティマイザーとコードジェネレーターによって認識される特定のメタデータノードの詳細については、以下を参照してください。

特殊化されたメタデータノード

特殊化されたメタデータノードは、メタデータ内のカスタムデータ構造です(一般的なタプルとは対照的)。そのフィールドにはラベルが付けられており、任意の順序で指定できます。

これらは本質的にデバッグ情報中心ではありませんが、現在、すべての特殊化されたメタデータノードはデバッグ情報に関連しています。

DICompileUnit

DICompileUnit ノードはコンパイルユニットを表します。enums:retainedTypes:globals:imports:、および macros: フィールドは、コード最適化に関係なく、コンパイルユニットとともにエミットされるデバッグ情報を含むタプルです(一部のノードは、命令からの参照がある場合にのみエミットされます)。debugInfoForProfiling: フィールドは、プロファイル結果に対してより正確なデバッグ情報を提供するために、ラインテーブルの判別子が更新されるかどうかを示すブール値です。

!0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
                    isOptimized: true, flags: "-O2", runtimeVersion: 2,
                    splitDebugFilename: "abc.debug", emissionKind: FullDebug,
                    enums: !2, retainedTypes: !3, globals: !4, imports: !5,
                    macros: !6, dwoId: 0x0abcd)

コンパイルユニット記述子は、特定のコンパイルユニットで宣言されたオブジェクトのルートスコープを提供します。ファイル記述子は、このスコープを使用して定義されます。これらの記述子は、名前付きメタデータノード !llvm.dbg.cu によって収集されます。これらは、グローバル変数、型情報、およびインポートされたエンティティ(宣言と名前空間)を追跡します。

DIFile

DIFile ノードはファイルを表します。filename: にはスラッシュを含めることができます。

!0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir",
             checksumkind: CSK_MD5,
             checksum: "000102030405060708090a0b0c0d0e0f")

ファイルは scope: フィールドで使用される場合があり、file: フィールドの唯一の有効なターゲットです。

checksum: フィールドと checksumkind: フィールドはオプションです。これらのフィールドのいずれかが存在する場合、もう一方も存在する必要があります。checksumkind: フィールドの有効な値は、{CSK_MD5, CSK_SHA1, CSK_SHA256} です。

DIBasicType

DIBasicType ノードは、intboolfloat などのプリミティブ型を表します。tag: はデフォルトで DW_TAG_base_type になります。

!0 = !DIBasicType(name: "unsigned char", size: 8, align: 8,
                  encoding: DW_ATE_unsigned_char)
!1 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)")

encoding: は型の詳細を記述します。通常、次のいずれかです。

DW_ATE_address       = 1
DW_ATE_boolean       = 2
DW_ATE_float         = 4
DW_ATE_signed        = 5
DW_ATE_signed_char   = 6
DW_ATE_unsigned      = 7
DW_ATE_unsigned_char = 8
DISubroutineType

DISubroutineType ノードは、サブルーチン型を表します。その types: フィールドはタプルを参照します。最初のオペランドは戻り値の型で、残りは順序どおりに仮引数の型です。最初のオペランドが null の場合、それは戻り値がない関数(C++ の void foo() {} など)を表します。

!0 = !BasicType(name: "int", size: 32, align: 32, DW_ATE_signed)
!1 = !BasicType(name: "char", size: 8, align: 8, DW_ATE_signed_char)
!2 = !DISubroutineType(types: !{null, !0, !1}) ; void (int, char)
DIDerivedType

DIDerivedType ノードは、修飾型など、他の型から派生した型を表します。

!0 = !DIBasicType(name: "unsigned char", size: 8, align: 8,
                  encoding: DW_ATE_unsigned_char)
!1 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !0, size: 32,
                    align: 32)

次の tag: 値が有効です。

DW_TAG_member             = 13
DW_TAG_pointer_type       = 15
DW_TAG_reference_type     = 16
DW_TAG_typedef            = 22
DW_TAG_inheritance        = 28
DW_TAG_ptr_to_member_type = 31
DW_TAG_const_type         = 38
DW_TAG_friend             = 42
DW_TAG_volatile_type      = 53
DW_TAG_restrict_type      = 55
DW_TAG_atomic_type        = 71
DW_TAG_immutable_type     = 75

DW_TAG_member は、複合型 のメンバーを定義するために使用されます。メンバーの型は baseType: です。offset: はメンバーのビットオフセットです。複合型に ODR identifier: があり、flags: DIFwdDecl を設定しない場合、メンバーは name:scope: のみに基づいてユニーク化されます。

DW_TAG_inheritanceDW_TAG_friend は、親とフレンドを記述するために、複合型elements: フィールドで使用されます。

DW_TAG_typedef は、baseType: の名前を提供するために使用されます。

DW_TAG_pointer_typeDW_TAG_reference_typeDW_TAG_const_typeDW_TAG_volatile_typeDW_TAG_restrict_typeDW_TAG_atomic_type、および DW_TAG_immutable_type は、baseType: を修飾するために使用されます。

void * 型は、NULL から派生した型として表されることに注意してください。

DICompositeType

DICompositeType ノードは、構造体や共用体のように、他の型で構成される型を表します。elements: は、構成された型のタプルを指します。

ソース言語が ODR をサポートしている場合、identifier: フィールドは、モジュール間の型マージに使用される一意の識別子を提供します。指定した場合、サブルーチン宣言 および メンバー派生型 は、scope: で ODR 型を参照する際、ユニーク化ルールを変更します。

特定の identifier: に対して、flags: DIFlagFwdDecl が設定されていない複合型は 1 つだけである必要があります。モジュールをリンクする LLVM ツールは、ノードが distinct であっても、解析時に identifier: フィールドを介してこのような定義をユニーク化します。

!0 = !DIEnumerator(name: "SixKind", value: 7)
!1 = !DIEnumerator(name: "SevenKind", value: 7)
!2 = !DIEnumerator(name: "NegEightKind", value: -8)
!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", file: !12,
                      line: 2, size: 32, align: 32, identifier: "_M4Enum",
                      elements: !{!0, !1, !2})

次の tag: 値が有効です。

DW_TAG_array_type       = 1
DW_TAG_class_type       = 2
DW_TAG_enumeration_type = 4
DW_TAG_structure_type   = 19
DW_TAG_union_type       = 23

DW_TAG_array_type の場合、elements:サブレンジ記述子である必要があります。各記述子は、インデックスのそのレベルでの添え字の範囲を表します。flags: に対する DIFlagVector フラグは、配列型がネイティブのパックされたベクターであることを示します。オプションの dataLocation は、オブジェクトのアドレスから実際の生データに到達する方法を記述する DIExpression です (それらが同等でない場合)。これは、特に Fortran 配列を記述する場合に、配列データに加えて配列記述子を持つ配列型でのみサポートされます。あるいは、実際の生データのアドレスを持つ DIVariable にすることもできます。Fortran 言語は、実際の配列にアタッチできるポインタ配列をサポートしており、ポインタとポインティ間のこのアタッチメントはアソシエーションと呼ばれます。オプションの associated は、ポインタ配列が現在関連付けられているかどうかを記述する DIExpression です。オプションの allocated は、割り当て可能な配列が現在割り当てられているかどうかを記述する DIExpression です。オプションの rank は、Fortran の想定ランク配列のランク (次元数) を記述する DIExpression です (ランクは実行時に認識されます)。

DW_TAG_enumeration_type の場合、elements:列挙子記述子である必要があります。各記述子は、セットの列挙値の定義を表します。すべての列挙型記述子は、コンパイルユニットenums: フィールドに収集されます。

DW_TAG_structure_typeDW_TAG_class_type、および DW_TAG_union_type の場合、elements:tag: DW_TAG_membertag: DW_TAG_inheritance、または tag: DW_TAG_friend を持つ 派生型である必要があります。または、isDefinition: false を持つ サブプログラムである必要があります。

DISubrange

DISubrange ノードは、DICompositeTypeDW_TAG_array_type バリアントの要素です。

  • count: -1 は、空の配列を示します。

  • count: !10 は、DILocalVariable を使用してカウントを記述します。

  • count: !12 は、DIGlobalVariable を使用してカウントを記述します。

!0 = !DISubrange(count: 5, lowerBound: 0) ; array counting from 0
!1 = !DISubrange(count: 5, lowerBound: 1) ; array counting from 1
!2 = !DISubrange(count: -1) ; empty array.

; Scopes used in rest of example
!6 = !DIFile(filename: "vla.c", directory: "/path/to/file")
!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !6)
!8 = distinct !DISubprogram(name: "foo", scope: !7, file: !6, line: 5)

; Use of local variable as count value
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!10 = !DILocalVariable(name: "count", scope: !8, file: !6, line: 42, type: !9)
!11 = !DISubrange(count: !10, lowerBound: 0)

; Use of global variable as count value
!12 = !DIGlobalVariable(name: "count", scope: !8, file: !6, line: 22, type: !9)
!13 = !DISubrange(count: !12, lowerBound: 0)
DIEnumerator

DIEnumerator ノードは、DICompositeTypeDW_TAG_enumeration_type バリアントの要素です。

!0 = !DIEnumerator(name: "SixKind", value: 7)
!1 = !DIEnumerator(name: "SevenKind", value: 7)
!2 = !DIEnumerator(name: "NegEightKind", value: -8)
DITemplateTypeParameter

DITemplateTypeParameter ノードは、ジェネリックソース言語構造の型パラメータを表します。これらは、DICompositeType および DISubprogramtemplateParams: フィールドで (オプションで) 使用されます。

!0 = !DITemplateTypeParameter(name: "Ty", type: !1)
DITemplateValueParameter

DITemplateValueParameter ノードは、ジェネリックソース言語構造の値パラメータを表します。tag: はデフォルトで DW_TAG_template_value_parameter になりますが、指定された場合は DW_TAG_GNU_template_template_param または DW_TAG_GNU_template_param_pack に設定することもできます。これらは、DICompositeType および DISubprogramtemplateParams: フィールドで (オプションで) 使用されます。

!0 = !DITemplateValueParameter(name: "Ty", type: !1, value: i32 7)
DINamespace

DINamespace ノードは、ソース言語の名前空間を表します。

!0 = !DINamespace(name: "myawesomeproject", scope: !1, file: !2, line: 7)
DIGlobalVariable

DIGlobalVariable ノードは、ソース言語のグローバル変数を表します。

@foo = global i32, !dbg !0
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !2,
                       file: !3, line: 7, type: !4, isLocal: true,
                       isDefinition: false, declaration: !5)
DIGlobalVariableExpression

DIGlobalVariableExpression ノードは、DIGlobalVariableDIExpression と結び付けます。

@lower = global i32, !dbg !0
@upper = global i32, !dbg !1
!0 = !DIGlobalVariableExpression(
         var: !2,
         expr: !DIExpression(DW_OP_LLVM_fragment, 0, 32)
         )
!1 = !DIGlobalVariableExpression(
         var: !2,
         expr: !DIExpression(DW_OP_LLVM_fragment, 32, 32)
         )
!2 = !DIGlobalVariable(name: "split64", linkageName: "split64", scope: !3,
                       file: !4, line: 8, type: !5, declaration: !6)

すべてのグローバル変数式は、コンパイルユニットglobals: フィールドで参照される必要があります。

DISubprogram

DISubprogram ノードは、ソース言語の関数を表します。個別の DISubprogram は、!dbg メタデータを使用して関数定義にアタッチできます。一意の DISubprogram は、呼び出しサイトのデバッグ情報に使用される関数宣言にアタッチできます。retainedNodes: フィールドは、IR カウンターパートが IR から最適化されていても保持する必要がある 変数および ラベルのリストです。type: フィールドは、DISubroutineType を指している必要があります。

spFlags: DISPFlagDefinition が存在しない場合、サブプログラムは関数の定義ではなく、型ツリー内の宣言を記述します。この場合、declaration フィールドは空である必要があります。スコープが ODR identifier: を持つ複合型であり、flags: DIFwdDecl を設定していない場合、サブプログラム宣言は、その linkageName:scope: のみに基づいて一意になります。

define void @_Z3foov() !dbg !0 {
  ...
}

!0 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1,
                            file: !2, line: 7, type: !3,
                            spFlags: DISPFlagDefinition | DISPFlagLocalToUnit,
                            scopeLine: 8, containingType: !4,
                            virtuality: DW_VIRTUALITY_pure_virtual,
                            virtualIndex: 10, flags: DIFlagPrototyped,
                            isOptimized: true, unit: !5, templateParams: !6,
                            declaration: !7, retainedNodes: !8,
                            thrownTypes: !9)
DILexicalBlock

DILexicalBlock ノードは、サブプログラム内のネストされたブロックを記述します。行番号と列番号は、同じ深度にある 2 つの字句ブロックを区別するために使用されます。これらは、scope: フィールドの有効なターゲットです。

!0 = distinct !DILexicalBlock(scope: !1, file: !2, line: 7, column: 35)

通常、字句ブロックは、オペランドに基づくノードのマージを防ぐために distinct です。

DILexicalBlockFile

DILexicalBlockFile ノードは、字句ブロックのセクションを区別するために使用されます。file: フィールドは、テキストのインクルードを示すように変更できます。または、discriminator: フィールドを使用して、ソース言語の単一ブロック内の制御フローを区別できます。

!0 = !DILexicalBlock(scope: !3, file: !4, line: 7, column: 35)
!1 = !DILexicalBlockFile(scope: !0, file: !4, discriminator: 0)
!2 = !DILexicalBlockFile(scope: !0, file: !4, discriminator: 1)
DILocation

DILocation ノードは、ソースデバッグの場所を表します。scope: フィールドは必須であり、DILexicalBlockFileDILexicalBlock、または DISubprogram を指します。

!0 = !DILocation(line: 2900, column: 42, scope: !1, inlinedAt: !2)
DILocalVariable

DILocalVariable ノードは、ソース言語のローカル変数を表します。arg: フィールドがゼロ以外に設定されている場合、この変数はサブプログラムパラメータであり、その DISubprogramretainedNodes: フィールドに含まれます。

!0 = !DILocalVariable(name: "this", arg: 1, scope: !3, file: !2, line: 7,
                      type: !3, flags: DIFlagArtificial)
!1 = !DILocalVariable(name: "x", arg: 2, scope: !4, file: !2, line: 7,
                      type: !3)
!2 = !DILocalVariable(name: "y", scope: !5, file: !2, line: 7, type: !3)
DIExpression

DIExpression ノードは、DWARF 式言語に触発された式を表します。これらは、デバッグレコード (#dbg_declare#dbg_value など) で使用され、参照された LLVM 変数がソース言語変数とどのように関連するかを記述します。デバッグ式は左から右に解釈されます。まず、レコードの値/アドレスオペランドをスタックにプッシュし、次に最終的な変数記述が生成されるまで、DIExpression からオペコードを繰り返しプッシュして評価します。

現在サポートされているオペコードの語彙は限られています

  • DW_OP_deref は、式スタックの最上位を逆参照します。

  • DW_OP_plus は、式スタックから最後の 2 つのエントリをポップし、それらを加算して、結果を式スタックに追加します。

  • DW_OP_minus は、式スタックから最後の 2 つのエントリをポップし、最後のエントリを最後から 2 番目のエントリから減算して、結果を式スタックに追加します。

  • DW_OP_plus_uconst, 93 は、ワーキングエクスプレッションに 93 を加算します。

  • DW_OP_LLVM_fragment, 16, 8 は、ワーキングエクスプレッションからの変数フラグメントのオフセットとサイズ(ここではそれぞれ 168)を指定します。DW_OP_bit_piece とは対照的に、オフセットは記述されたソース変数内の位置を表すことに注意してください。

  • DW_OP_LLVM_convert, 16, DW_ATE_signed は、式のスタックの最上位を変換するビットサイズとエンコーディング(ここではそれぞれ 16DW_ATE_signed)を指定します。指定された値から構築された基本型を参照する DW_OP_convert 操作にマップされます。

  • DW_OP_LLVM_extract_bits_sext, 16, 8, は、式のスタックの最上位の値から抽出して符号拡張するビットのオフセットとサイズ(ここではそれぞれ 168)を指定します。式のスタックの最上位がメモリ位置である場合、これらのビットはそのメモリ位置が指す値から抽出されます。DW_OP_shl に続いて DW_OP_shra にマップされます。

  • DW_OP_LLVM_extract_bits_zextDW_OP_LLVM_extract_bits_sext と同様に動作しますが、符号拡張の代わりにゼロ拡張します。DW_OP_shl に続いて DW_OP_shr にマップされます。

  • DW_OP_LLVM_tag_offset, tag_offset は、メモリタグをポインタにオプションで適用する必要があることを指定します。メモリタグは、実装定義の方法で指定されたタグオフセットから導出されます。

  • DW_OP_swap は、スタックの最上位 2 つのエントリを交換します。

  • DW_OP_xderef は、拡張された間接参照メカニズムを提供します。スタックの最上位のエントリはアドレスとして扱われます。2 番目のスタックエントリは、アドレス空間識別子として扱われます。

  • DW_OP_stack_value は定数値をマークします。

  • DW_OP_LLVM_entry_value, N は、関数エントリ時のレジスタが持っていた値を参照します。DWARF をターゲットとする場合、DBG_VALUE(reg, ..., DIExpression(DW_OP_LLVM_entry_value, 1, ...)DW_OP_entry_value [reg], ... に下げられ、関数エントリ時に reg が持っていた値を DWARF 式スタックにプッシュします。

    次の (N - 1) 操作は、DW_OP_entry_value ブロック引数の一部になります。たとえば、!DIExpression(DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 123, DW_OP_stack_value) は、reg のエントリ値がスタックにプッシュされ、123 が加算される式を指定します。フレームワークの制限により、N は 1 でなければなりません。つまり、DW_OP_entry_value は常に命令の値/アドレス オペランドを参照します。

    DW_OP_LLVM_entry_value はレジスタに関して定義されているため、通常は MIR で使用されますが、swiftasync 引数をターゲットとする場合、LLVM IR でも許可されます。この操作は以下によって導入されます。

    • LiveDebugValues パスは、関数全体で変更されない関数パラメータに適用します。サポートは、単純なレジスタ位置記述、または間接的な位置(たとえば、呼び出し元で作成された一時コピーへのポインタを介して呼び出し先に値渡しされるパラメータ)に限定されます。

    • 呼び出しサイトパラメータ値(DW_AT_call_site_parameter_value)がパラメータのエントリ値として表される場合の AsmPrinter パス。

    • アロカからコルーチンフレームに変数を移動することがある CoroSplit パス。コルーチンフレームが swiftasync 引数である場合、変数は DW_OP_LLVM_entry_value 操作で記述されます。

  • DW_OP_LLVM_arg, N は、2 つのレジスタの合計を計算するものなど、複数の値を参照するデバッグイントリンシックで使用されます。これは常に値の順序付きリストと組み合わせて使用​​され、DW_OP_LLVM_arg, N はそのリストの N 番目の要素を参照します。たとえば、リスト (%reg1, %reg2) で使用される !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_minus, DW_OP_stack_value) は、%reg1 - reg2 と評価されます。この値のリストは、包含するイントリンシック/命令によって提供される必要があります。

  • DW_OP_breg (または DW_OP_bregx) は、指定されたレジスタの指定された符号付きオフセットの内容を表します。このオペコードは、2 つのレジスタにわたる式を必要とする呼び出しサイトパラメータ値を記述するために、AsmPrinter パスによってのみ生成されます。

  • DW_OP_push_object_address は、その後の計算で記述子として機能できるオブジェクトのアドレスをプッシュします。このオペコードは、配列記述子を持つ fortran 配列の割り当て可能な境界を計算するために使用できます。

  • DW_OP_over は、スタックの現在 2 番目のエントリをスタックの最上位に複製します。このオペコードは、実行時にランクが既知であり、現在の次元番号が暗黙的にスタックの最初の要素である fortran 想定ランク配列の境界を計算するために使用できます。

  • DW_OP_LLVM_implicit_pointer は、間接参照された値を指定します。最適化されたが、それが指す値は既知であるポインタ変数を表すために使用できます。この演算子は、表現と仕様(オペランドの数と型)が DWARF 演算子 DW_OP_implicit_pointer と異なり、後者は複数レベルで使用できないため、必要です。

IR for "*ptr = 4;"
--------------
  #dbg_value(i32 4, !17, !DIExpression(DW_OP_LLVM_implicit_pointer), !20)
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
                       type: !18)
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!20 = !DILocation(line: 10, scope: !12)

IR for "**ptr = 4;"
--------------
  #dbg_value(i32 4, !17,
    !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_implicit_pointer),
    !21)
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
                       type: !18)
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!21 = !DILocation(line: 10, scope: !12)

DWARF は、レジスタ、メモリ、暗黙的な位置記述の 3 種類の単純な位置記述を指定します。位置記述はプログラムの特定の範囲で定義されることに注意してください。つまり、変数の位置はプログラムの過程で変化する可能性があります。レジスタとメモリの位置記述は、ソース変数の具体的な位置(デバッガーがその値を変更できるという意味で)を表しますが、暗黙的な位置は、レジスタまたはメモリに存在しない可能性のあるソース変数の単なる実際のを表します(DW_OP_stack_value を参照)。

#dbg_declare レコードは、ソース変数の間接的な値(アドレス)を記述します。レコードの最初のオペランドは、何らかのアドレスである必要があります。レコードへの DIExpression オペランドは、このアドレスを絞り込んでソース変数の具体的な位置を生成します。

#dbg_value レコードは、ソース変数の直接的な値を記述します。レコードの最初のオペランドは、直接または間接的な値にすることができます。レコードへの DIExpression オペランドは、最初のオペランドを絞り込んで直接的な値を生成します。たとえば、最初のオペランドが間接的な値である場合、有効なデバッグレコードを生成するために DW_OP_deref を DIExpression に挿入する必要がある場合があります。

注記

DIExpression は、アタッチされているデバッグレコードの種類に関係なく、同じように解釈されます。

DIExpression は常にインラインで印刷および解析されます。ID (例: !1) で参照することはできません。

!DIExpression(DW_OP_deref)
!DIExpression(DW_OP_plus_uconst, 3)
!DIExpression(DW_OP_constu, 3, DW_OP_plus)
!DIExpression(DW_OP_bit_piece, 3, 7)
!DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_fragment, 3, 7)
!DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
!DIExpression(DW_OP_constu, 42, DW_OP_stack_value)
DIAssignID

DIAssignID ノードにはオペランドがなく、常に区別されます。これらは、(#dbg_assign レコード)と IR に格納する命令をリンクするために使用されます。詳細については、デバッグ情報代入追跡を参照してください。

store i32 %a, ptr %a.addr, align 4, !DIAssignID !2
#dbg_assign(%a, !1, !DIExpression(), !2, %a.addr, !DIExpression(), !3)

!2 = distinct !DIAssignID()
DIArgList

DIArgList ノードは、定数または SSA 値参照のリストを保持します。これらは、デバッグレコードDW_OP_LLVM_arg 演算子を使用する DIExpression と組み合わせて使用されます。DIArgList は関数内のローカル値を参照する可能性があるため、関数の引数としてのみ使用する必要があり、常にインライン化する必要があり、名前付きメタデータに表示することはできません。

#dbg_value(!DIArgList(i32 %a, i32 %b),
           !16,
           !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus),
           !26)
DIFlags

これらのフラグは、DINode のさまざまなプロパティをエンコードします。

ExportSymbols フラグは、メンバーが、それらを包含するクラスやユニオン内で定義されているかのように参照できるクラス、構造体、またはユニオンをマークします。このフラグは、構造体型に DW_AT_export_symbols を使用できるかどうかを判断するために使用されます。

DIObjCProperty

DIObjCProperty ノードは、Objective-C のプロパティノードを表します。

!3 = !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo",
                     getter: "getFoo", attributes: 7, type: !2)
DIImportedEntity

DIImportedEntity ノードは、コンパイルユニットにインポートされたエンティティ(モジュールなど)を表します。 elements フィールドは、インポートされたエンティティ(モジュールなど)内の名前が変更されたエンティティ(変数やサブプログラムなど)のリストです。

!2 = !DIImportedEntity(tag: DW_TAG_imported_module, name: "foo", scope: !0,
                       entity: !1, line: 7, elements: !3)
!3 = !{!4}
!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "bar", scope: !0,
                       entity: !5, line: 7)
DIMacro

DIMacro ノードは、マクロ識別子の定義または未定義を表します。 name: フィールドはマクロ識別子で、関数のようなマクロを定義する場合はマクロパラメータが続き、value フィールドはマクロ識別子を展開するために使用されるトークン文字列です。

!2 = !DIMacro(macinfo: DW_MACINFO_define, line: 7, name: "foo(x)",
              value: "((x) + 1)")
!3 = !DIMacro(macinfo: DW_MACINFO_undef, line: 30, name: "foo")
DIMacroFile

DIMacroFile ノードは、ソースファイルのインクルードを表します。 nodes: フィールドは、インクルードされたソースファイルに現れる DIMacro および DIMacroFile ノードのリストです。

!2 = !DIMacroFile(macinfo: DW_MACINFO_start_file, line: 7, file: !2,
                  nodes: !3)
DILabel

DILabel ノードは、DISubprogram 内のラベルを表します。 DILabel のすべてのフィールドは必須です。 scope: フィールドは、DILexicalBlockFileDILexicalBlock、または DISubprogram のいずれかでなければなりません。 name: フィールドはラベル識別子です。 file: フィールドは、ラベルが存在する DIFile です。 line: フィールドは、ラベルが宣言されているファイル内のソース行です。

!2 = !DILabel(scope: !0, name: "foo", file: !1, line: 7)
DICommonBlock

DICommonBlock ノードは、Fortran の共通ブロックを表します。 scope: フィールドは必須であり、DILexicalBlockFileDILexicalBlock、または DISubprogram を指します。 declaration:name:file:、および line: フィールドはオプションです。

DIModule

DIModule ノードは、ソース言語モジュール(たとえば、Clang モジュールや Fortran モジュール)を表します。 scope: フィールドは必須であり、DILexicalBlockFileDILexicalBlock、または DISubprogram を指します。 name: フィールドは必須です。 configMacros:includePath:apinotes:file:line:、および isDecl: フィールドはオプションです。

DIStringType

DIStringType ノードは、動的な長さと式としてエンコードされた位置を持つ Fortran の CHARACTER(n) 型を表します。 tag: フィールドはオプションで、デフォルトは DW_TAG_string_type です。 name:stringLength:stringLengthExpressionstringLocationExpression:size:align:、および encoding: フィールドはオプションです。

存在しない場合、size: フィールドと align: フィールドはデフォルトでゼロになります。

文字列のビット単位の長さは、次のフィールドのうち最初に存在するもので指定されます。

  • stringLength: は、値がビット単位の文字列長である DIVariable を指します。

  • stringLengthExpression: は、ビット単位の長さを計算する DIExpression を指します。

  • size は、ビット単位のリテラル長を含みます。

stringLocationExpression: は、存在する場合、文字列オブジェクトの「データ位置」を記述する DIExpression を指します。

tbaa」メタデータ

LLVM IR では、メモリには型がないため、LLVM 自身の型システムは、型に基づいたエイリアス解析 (TBAA) を行うには適していません。代わりに、より高水準の言語の型システムを記述するメタデータが IR に追加されます。これは、C/C++ の厳密な型エイリアス規則を実装するために使用できますが、他の言語のカスタムエイリアス解析動作を実装するためにも使用できます。

この LLVM の TBAA システムの説明は、2 つの部分に分かれています。 セマンティクス は高レベルの問題について説明し、 表現 はさまざまなエンティティのメタデータエンコーディングについて説明します。

常に、任意の TBAA ノードを「ルート」TBAA ノードまでトレースできます(詳細は 表現 セクションを参照)。異なるルートを持つ TBAA ノードは、エイリアス関係が不明であり、LLVM はそれらの間で MayAlias を保守的に推論します。このセクションで言及されているルールは、同じルートの下にある TBAA ノードにのみ適用されます。

セマンティクス

「構造体パス TBAA」(tbaa.struct と混同しないでください)と呼ばれる TBAA メタデータシステムは、次の高レベルの概念で構成されています。型記述子、さらにスカラー型記述子と構造体型記述子に細分されます。およびアクセスタグ

型記述子は、コンパイルされている高水準言語の型システムを記述します。スカラー型記述子は、他の型を含まない型を記述します。各スカラー型には、親型があります。親型もスカラー型または TBAA ルートである必要があります。この親子関係を通じて、TBAA ルート内のスカラー型はツリーを形成します。構造体型記述子は、既知のオフセットで他の型記述子のシーケンスを含む型を示します。これらの含まれる型記述子は、構造体型記述子自体またはスカラー型記述子のいずれかです。

アクセスタグは、ロード命令とストア命令にアタッチされたメタデータノードです。アクセスタグは、高水準言語の型システムの観点から、アクセスされている位置を記述するために型記述子を使用します。アクセスタグは、ベース型、アクセス型、およびオフセットで構成されるタプルです。ベース型はスカラー型記述子または構造体型記述子であり、アクセス型はスカラー型記述子であり、オフセットは定数整数です。

アクセスタグ (BaseTy, AccessTy, Offset) は、次の 2 つのいずれかを記述できます。

  • BaseTy が構造体型の場合、タグは、オフセット Offset で構造体型 BaseTy に含まれる型 AccessTy の値のメモリアクセス(ロードまたはストア)を記述します。

  • BaseTy がスカラー型の場合、Offset は 0 でなければならず、BaseTyAccessTy は同じでなければなりません。そして、アクセスタグはスカラー型 AccessTy を持つスカラーアクセスを記述します。

まず、(BaseTy, Offset) タプルに対して、ImmediateParent 関係を以下のように定義します。

  • BaseTy がスカラー型の場合、ImmediateParent(BaseTy, 0)(ParentTy, 0) となります。ここで、ParentTy はTBAAメタデータで記述されているスカラー型の親型です。Offset がゼロ以外の場合、ImmediateParent(BaseTy, Offset) は未定義です。

  • BaseTy が構造体型の場合、ImmediateParent(BaseTy, Offset)(NewTy, NewOffset) となります。ここで、NewTyOffset のオフセットで BaseTy に含まれる型であり、NewOffset はその内部型内で相対的なオフセットになるように調整された Offset です。

アクセス・タグ (BaseTy1, AccessTy1, Offset1) を持つメモリアクセスは、アクセス・タグ (BaseTy2, AccessTy2, Offset2) を持つメモリアクセスとエイリアスします。これは、(BaseTy1, Offset1)Parent 関係を介して (Base2, Offset2) から到達可能であるか、またはその逆の場合です。

具体的な例として、次のプログラムの型記述子グラフは以下のようになります。

struct Inner {
  int i;    // offset 0
  float f;  // offset 4
};

struct Outer {
  float f;  // offset 0
  double d; // offset 4
  struct Inner inner_a;  // offset 12
};

void f(struct Outer* outer, struct Inner* inner, float* f, int* i, char* c) {
  outer->f = 0;            // tag0: (OuterStructTy, FloatScalarTy, 0)
  outer->inner_a.i = 0;    // tag1: (OuterStructTy, IntScalarTy, 12)
  outer->inner_a.f = 0.0;  // tag2: (OuterStructTy, FloatScalarTy, 16)
  *f = 0.0;                // tag3: (FloatScalarTy, FloatScalarTy, 0)
}

(CおよびC++では、char を使用して任意の型にアクセスできることに注意してください)

Root = "TBAA Root"
CharScalarTy = ("char", Root, 0)
FloatScalarTy = ("float", CharScalarTy, 0)
DoubleScalarTy = ("double", CharScalarTy, 0)
IntScalarTy = ("int", CharScalarTy, 0)
InnerStructTy = {"Inner" (IntScalarTy, 0), (FloatScalarTy, 4)}
OuterStructTy = {"Outer", (FloatScalarTy, 0), (DoubleScalarTy, 4),
                 (InnerStructTy, 12)}

(例えば) ImmediateParent(OuterStructTy, 12) = (InnerStructTy, 0), ImmediateParent(InnerStructTy, 0) = (IntScalarTy, 0), そして ImmediateParent(IntScalarTy, 0) = (CharScalarTy, 0) です。

表現

TBAA型階層のルートノードは、0個のオペランドを持つ MDNode または、正確に1つの MDString オペランドを持つ MDNode です。

スカラー型記述子は、2つのオペランドを持つ MDNode として表現されます。最初のオペランドは構造体型の名前を示す MDString です。LLVMはこのオペランドの値に意味を割り当てず、それが MDString であることのみを気にします。2番目のオペランドは、当該スカラー型記述子の親を指す MDNode であり、これは別のスカラー型記述子またはTBAAルートのいずれかです。スカラー型記述子はオプションで3番目の引数を持つことができますが、それは定数整数のゼロでなければなりません。

構造体型記述子は、1より大きい奇数のオペランドを持つ MDNode として表現されます。最初のオペランドは構造体型の名前を示す MDString です。スカラー型記述子のように、この名前オペランドの実際の値はLLVMには無関係です。名前オペランドの後、構造体型記述子は交互に MDNode オペランドと ConstantInt オペランドのシーケンスを持ちます。Nを1から始めると、2N-1番目のオペランドである MDNode は含まれるフィールドを示し、2N番目のオペランドである ConstantInt は当該含まれるフィールドのオフセットです。オフセットは非減少順である必要があります。

アクセス・タグは、3つまたは4つのオペランドを持つ MDNode として表現されます。最初のオペランドはベース型を表すノードを指す MDNode です。2番目のオペランドはアクセス型を表すノードを指す MDNode です。3番目のオペランドはアクセスのオフセットを示す ConstantInt です。4番目のフィールドが存在する場合、それは0または1の値を持つ ConstantInt である必要があります。それが1の場合、アクセス・タグはアクセスされている場所が「定数」であることを示します(つまり、pointsToConstantMemory がtrueを返す必要があります。 他の有用なAliasAnalysisメソッドを参照)。アクセス型のTBAAルートとアクセス・タグのベース型は同じである必要があり、それがアクセス・タグのTBAAルートです。

tbaa.struct」メタデータ

llvm.memcpy は、Cや類似の言語で集約代入操作を実装するためによく使用されますが、パディングによる穴を含む集約型に厳密に必要な量よりも多くの連続したメモリ領域をコピーするように定義されています。また、集約型のフィールドに関するTBAA情報は含まれていません。

!tbaa.struct メタデータは、memcpy内のどのメモリサブ領域がパディングであり、構造体のTBAAタグが何であるかを記述できます。

現在のメタデータ形式は非常に単純です。!tbaa.struct メタデータノードは、概念的に3つのグループに分けられたオペランドのリストです。3つのグループごとに、最初のオペランドはフィールドのバイトオフセットをバイト単位で、2番目はバイト単位でのサイズ、3番目はそのtbaaタグを指定します。例:

!4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 }

これは、2つのフィールドを持つ構造体を記述しています。1つ目はオフセット0バイトにあり、サイズは4バイトで、tbaaタグは!1です。2つ目はオフセット8バイトにあり、サイズは4バイトで、tbaaタグは!2です。

フィールドが連続している必要はないことに注意してください。この例では、2つのフィールド間に4バイトのギャップがあります。このギャップは、有用なデータを保持せず、保存する必要のないパディングを表しています。

noalias」および「alias.scope」メタデータ

noalias メタデータと alias.scope メタデータは、汎用のnoaliasメモリアクセスセットを指定する機能を提供します。つまり、noalias メタデータを持つ一部のメモリアクセス命令(ロード、ストア、メモリアクセス呼び出しなど)は、alias.scope メタデータを持つ他のメモリアクセス命令のコレクションとエイリアスしないように明示的に指定できます。各メタデータの種類は、各スコープがIDとドメインを持つスコープのリストを指定します。

エイリアス・クエリを評価する際、あるドメインについて、ある命令の alias.scope リストのそのドメインを持つスコープのセットが、別の命令の noalias リストのそのドメインのスコープのセットのサブセットである(または等しい)場合、2つのメモリアクセスはエイリアスしないと見なされます。

あるドメインのスコープは別のドメインのスコープに影響を与えないため、複数の独立したnoaliasセットを構成するために個別のドメインを使用できます。これは、例えばインライン化中に使用されます。noalias関数パラメーターがnoaliasスコープメタデータに変換されると、関数がインライン化されるたびに新しいドメインが使用されます。

各ドメインを識別するメタデータ自体は、1つまたは2つのエントリを含むリストです。最初のエントリはドメインの名前です。名前が文字列の場合、関数および変換ユニット間で結合できることに注意してください。自己参照を使用して、グローバルに一意のドメイン名を作成できます。記述的な文字列は、オプションで2番目のリストエントリとして提供できます。

各スコープを識別するメタデータも、2つまたは3つのエントリを含むリストです。最初のエントリはスコープの名前です。名前が文字列の場合、関数および変換ユニット間で結合できることに注意してください。自己参照を使用して、グローバルに一意のスコープ名を作成できます。スコープのドメインへのメタデータ参照が2番目のエントリです。記述的な文字列は、オプションで3番目のリストエントリとして提供できます。

例:

; Two scope domains:
!0 = !{!0}
!1 = !{!1}

; Some scopes in these domains:
!2 = !{!2, !0}
!3 = !{!3, !0}
!4 = !{!4, !1}

; Some scope lists:
!5 = !{!4} ; A list containing only scope !4
!6 = !{!4, !3, !2}
!7 = !{!3}

; These two instructions don't alias:
%0 = load float, ptr %c, align 4, !alias.scope !5
store float %0, ptr %arrayidx.i, align 4, !noalias !5

; These two instructions also don't alias (for domain !1, the set of scopes
; in the !alias.scope equals that in the !noalias list):
%2 = load float, ptr %c, align 4, !alias.scope !5
store float %2, ptr %arrayidx.i2, align 4, !noalias !6

; These two instructions may alias (for domain !0, the set of scopes in
; the !noalias list is not a superset of, or equal to, the scopes in the
; !alias.scope list):
%2 = load float, ptr %c, align 4, !alias.scope !6
store float %0, ptr %arrayidx.i, align 4, !noalias !7

fpmath」メタデータ

fpmath メタデータは、浮動小数点型の任意の命令にアタッチできます。これにより、その命令の結果で許容される最大誤差をULP単位で表現できるため、コンパイラは、より効率的だが精度が低い計算方法を使用できる可能性があります。ULPは次のように定義されます。

実数 x が、2つの連続する有限浮動小数点数 ab の間にあり、どちらとも等しくない場合、ulp(x) = |b - a| となります。そうでない場合、ulp(x) は、x に最も近い2つの異なる有限浮動小数点数間の距離です。さらに、ulp(NaN)NaN です。

メタデータノードは、最大相対誤差を表す単一の正の浮動小数点数で構成される必要があります。例えば、

!0 = !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs

range」メタデータ

range メタデータは、整数型または整数ベクトル型の loadcall、および invoke にのみ付与できます。これは、ロードされた値またはこの呼び出しサイトで呼び出された関数が返す可能性のある範囲を表します。ロードされた値または返された値が指定された範囲内にない場合、代わりにポイズン値が返されます。範囲は、整数のフラット化されたリストで表されます。ロードされた値または返された値は、連続する各ペアによって定義された範囲の和集合内にあることがわかっています。各ペアは、次のプロパティを持ちます。

  • 型は、命令のスカラー型と一致する必要があります。

  • ペア a,b は、範囲 [a,b) を表します。

  • ab は両方とも定数です。

  • 範囲はラップすることが許可されています。

  • 範囲は、全集合または空集合を表してはなりません。つまり、a!=b である必要があります。

さらに、ペアは下限の符号付き順で並べられており、連続していてはなりません。

ベクトル型命令の場合、範囲は要素ごとに適用されます。

  %a = load i8, ptr %x, align 1, !range !0 ; Can only be 0 or 1
  %b = load i8, ptr %y, align 1, !range !1 ; Can only be 255 (-1), 0 or 1
  %c = call i8 @foo(),       !range !2 ; Can only be 0, 1, 3, 4 or 5
  %d = invoke i8 @bar() to label %cont
         unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5
  %e = load <2 x i8>, ptr %x, !range 0 ; Can only be <0 or 1, 0 or 1>
...
!0 = !{ i8 0, i8 2 }
!1 = !{ i8 255, i8 2 }
!2 = !{ i8 0, i8 2, i8 3, i8 6 }
!3 = !{ i8 -2, i8 0, i8 3, i8 6 }

absolute_symbol」メタデータ

absolute_symbol メタデータは、グローバル変数宣言に付与できます。これは、宣言を絶対シンボルへの参照としてマークし、バックエンドが位置独立コードでもシンボルに絶対的な再配置を使用するようにし、グローバル変数のアドレス(値ではない)が取りうる範囲を range メタデータと同じ形式で表現します。ただし、ペア all-ones,all-ones を使用して全集合を表すことができるという拡張があります。

例(64ビットポインタを想定)

  @a = external global i8, !absolute_symbol !0 ; Absolute symbol in range [0,256)
  @b = external global i8, !absolute_symbol !1 ; Absolute symbol in range [0,2^64)

...
!0 = !{ i64 0, i64 256 }
!1 = !{ i64 -1, i64 -1 }

callees」メタデータ

callees メタデータは、間接呼び出しサイトに付与できます。callees メタデータが呼び出しサイトに付与されており、いずれかの呼び出し先がメタデータによって提供される関数のセットに含まれていない場合、動作は未定義です。このメタデータの目的は、間接呼び出しの昇格などの最適化を促進することです。たとえば、以下のコードでは、call命令は add または sub 関数のみをターゲットにすることができます。

%result = call i64 %binop(i64 %x, i64 %y), !callees !0

...
!0 = !{ptr @add, ptr @sub}

callback」メタデータ

callback メタデータは、関数宣言または定義に付与できます。(呼び出しサイトは、ユースケースがないため除外されています。)説明を容易にするために、メタデータで注釈付けされた関数をブローカー関数と呼びます。このメタデータは、ブローカーへの呼び出しの引数が、メタデータによって指定されたコールバック関数にどのように渡されるかを記述します。したがって、callback メタデータは、ブローカーへの呼び出しの引数に関して、ブローカー関数内の呼び出しサイトの部分的な記述を提供します。ブローカー関数自体の唯一のセマンティックな制約は、コールバック関数へのパススルーとして callback メタデータで参照される引数を調べたり、変更したりすることが許可されていないことです。

ブローカーは、実行時に実際にコールバック関数を呼び出す必要はありません。ただし、指定されたコールバック関数に渡される引数を調べたり変更したりしないという仮定は、コールバック関数が動的に呼び出されない場合でも保持されます。ブローカーは、ブローカーの呼び出しごとにコールバック関数を複数回呼び出すことができます。ブローカーは、(直接または間接的に)別の用途を通じてコールバックとして渡された関数を呼び出すこともできます。最後に、ブローカーはコールバックの呼び出しを別のスレッドに中継することもできます。

メタデータは次のように構成されています。外側のレベルでは、callback メタデータは callback エンコーディングのリストです。各エンコーディングは、ブローカーへの呼び出しにおけるコールバック関数の引数位置を記述する定数 i64 で始まります。最後の要素を除く、次の要素は、コールバック関数に渡される引数を記述します。各要素は、再び、渡されるブローカーの引数を識別する i64 定数であるか、不明または検査された引数を示す i64 -1 です。それらがリストされる順序は、コールバックの呼び出し先に渡される順序と同じである必要があります。エンコーディングの最後の要素は、ブローカーの可変長引数がどのように処理されるかを指定するブール値です。それが true の場合、ブローカーのすべての可変長引数は、前に明示的にエンコードされた引数のにコールバック関数に渡されます。

以下のコードでは、pthread_create 関数は、!callback !1 メタデータを通じてブローカーとしてマークされています。この例では、ブローカーに関連付けられたコールバックエンコーディングは !2 の1つのみです。このエンコーディングは、コールバック関数をブローカーの2番目の引数(i64 2)として識別し、コールバック関数の唯一の引数をブローカー関数の3番目の引数(i64 3)として識別します。

declare !callback !1 dso_local i32 @pthread_create(ptr, ptr, ptr, ptr)

...
!2 = !{i64 2, i64 3, i1 false}
!1 = !{!2}

別の例を以下に示します。コールバックの呼び出し先は、__kmpc_fork_call 関数の2番目の引数(i64 2)です。呼び出し先には、2つの不明な値(それぞれ i64 -1 で識別される)が与えられ、その後、__kmpc_fork_call 呼び出しに渡されるすべての可変長引数(最後の i1 true のため)が与えられます。

declare !callback !0 dso_local void @__kmpc_fork_call(ptr, i32, ptr, ...)

...
!1 = !{i64 2, i64 -1, i64 -1, i1 true}
!0 = !{!1}

exclude」メタデータ

exclude メタデータは、グローバル変数に付与して、そのセクションが最終的な実行可能ファイルまたは共有ライブラリに含められないようにすることができます。このオプションは、ELFまたはCOFFを対象とした明示的なセクションを持つグローバル変数に対してのみ有効です。これは、ELFターゲットでは SHF_EXCLUDE フラグを使用し、COFFターゲットでは IMAGE_SCN_LNK_REMOVE および IMAGE_SCN_MEM_DISCARDABLE フラグを使用して行います。さらに、このメタデータはフラグとしてのみ使用されるため、関連付けられたノードは空である必要があります。明示的なセクションは、リンク後に削除したくない他のセクションと競合しないようにする必要があります。

@object = private constant [1 x i8] c"\00", section ".foo" !exclude !0

...
!0 = !{}

unpredictable」メタデータ

unpredictable メタデータは、任意の分岐またはswitch命令に付与できます。これは、制御フローの予測不可能性を表すために使用できます。llvm.expect 組み込み関数と同様に、比較および分岐命令に関連する最適化を変更するために使用できます。メタデータはブール値として扱われます。存在する場合、付与された分岐またはswitchが完全に予測不可能であることを示します。

dereferenceable」メタデータ

命令に !dereferenceable メタデータが存在するということは、ロードされた値が逆参照可能であることがわかっていることをオプティマイザーに示します。そうでない場合、動作は未定義です。逆参照可能であることがわかっているバイト数は、メタデータノードの整数値によって指定されます。これは、パラメータと戻り値の「逆参照可能」属性に類似しています。

dereferenceable_or_null」メタデータ

命令に !dereferenceable_or_null メタデータが存在する場合、オプティマイザはロードされた値が参照可能であるか null であるかのいずれかであることがわかっていることを示します。そうでない場合、動作は未定義です。参照可能であることがわかっているバイト数は、メタデータノードの整数値で指定されます。これは、パラメータと戻り値の "dereferenceable_or_null" 属性に類似しています。

llvm.loop

ループ構造に情報を付加すると便利な場合があります。現在、ループメタデータはループラッチブロック内の分岐命令に付加されたメタデータとして実装されています。ループメタデータノードは、ループのプロパティを表す他のメタデータノードのリストです。通常、プロパティノードの最初の項目は文字列です。たとえば、llvm.loop.unroll.count はループアンローラーへのアンロールファクタを示唆します。

  br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0
...
!0 = !{!0, !1, !2}
!1 = !{!"llvm.loop.unroll.enable"}
!2 = !{!"llvm.loop.unroll.count", i32 4}

レガシー上の理由から、ループメタデータノードの最初の項目はそれ自身への参照でなければなりません。 ‘distinct’ キーワードが登場する前は、これにより、そうでなければ同一のメタデータノードの保持が強制されました。ループメタデータノードは複数のノードに付加できるため、 ‘distinct’ キーワードは不要になりました。

プロパティノードの前に、1つまたは2つの DILocation (デバッグロケーション)ノードがリストに存在することができます。存在する場合、最初のノードはループが開始されるソースコードの場所を識別します。存在する場合、2番目のノードはループが終了するソースコードの場所を識別します。

ループメタデータノードは、一意の識別子として使用することはできません。変換を通じて同じループに対して永続的であることも、必ずしも1つのループに固有であるとも限りません。

llvm.loop.disable_nonforced

このメタデータは、llvm.loop.unroll.enable などの他の変換メタデータを使用して明示的に指示されない限り、すべてのオプションのループ変換を無効にします。つまり、変換が有益であるかどうかを判断しようとするヒューリスティックはありません。その目的は、明示的に要求された(強制された)変換が適用される前に、ループが別のループに変換されるのを防ぐことです。たとえば、ループ融合は他の変換を不可能にする可能性があります。ループ回転などの必須のループ正規化は、引き続き適用されます。

llvm.loop.* 変換ディレクティブに加えて、このメタデータを使用することをお勧めします。また、任意のループには、最大で1つのディレクティブのみを適用する必要があります(および後続属性を使用して構築された一連の変換)。そうしないと、どの変換が適用されるかは、パスパイプラインの順序などの実装詳細に依存します。

詳細については、コード変換メタデータを参照してください。

llvm.loop.vectorize’ および ‘llvm.loop.interleave

llvm.loop.vectorize または llvm.loop.interleave で始まるメタデータは、ベクトル化幅やインターリーブ数など、ループごとのベクトル化およびインターリーブパラメータを制御するために使用されます。これらのメタデータは、llvm.loop ループ識別メタデータと組み合わせて使用する必要があります。llvm.loop.vectorize および llvm.loop.interleave メタデータは最適化のヒントにすぎず、オプティマイザはそうすることが安全であると判断した場合にのみループをインターリーブおよびベクトル化します。ループキャリーメモリー依存関係に関する情報を含む llvm.loop.parallel_accesses メタデータは、これらの変換の安全性を判断するのに役立ちます。

llvm.loop.interleave.count’ メタデータ

このメタデータは、ループインターリーバーへのインターリーブ数を提案します。最初のオペランドは文字列 llvm.loop.interleave.count であり、2番目のオペランドはインターリーブ数を指定する整数です。例えば

!0 = !{!"llvm.loop.interleave.count", i32 4}

llvm.loop.interleave.count を 1 に設定すると、ループの複数の反復のインターリーブが無効になることに注意してください。llvm.loop.interleave.count が 0 に設定されている場合、インターリーブ数は自動的に決定されます。

llvm.loop.vectorize.enable’ メタデータ

このメタデータは、ループのベクトル化を選択的に有効または無効にします。最初のオペランドは文字列 llvm.loop.vectorize.enable であり、2番目のオペランドはビットです。ビットオペランド値が 1 の場合、ベクトル化が有効になります。値が 0 の場合は、ベクトル化が無効になります。

!0 = !{!"llvm.loop.vectorize.enable", i1 0}
!1 = !{!"llvm.loop.vectorize.enable", i1 1}

llvm.loop.vectorize.predicate.enable’ メタデータ

このメタデータは、ループに対して条件付き命令を作成することを選択的に有効または無効にします。これにより、スカラーエピローグループのメインループへの折り畳みを有効にできます。最初のオペランドは文字列 llvm.loop.vectorize.predicate.enable であり、2番目のオペランドはビットです。ビットオペランド値が 1 の場合、ベクトル化が有効になります。値が 0 の場合は、ベクトル化が無効になります。

!0 = !{!"llvm.loop.vectorize.predicate.enable", i1 0}
!1 = !{!"llvm.loop.vectorize.predicate.enable", i1 1}

llvm.loop.vectorize.scalable.enable’ メタデータ

このメタデータは、ループのスケーラブルなベクトル化を選択的に有効または無効にします。これは、ループのベクトル化が既に有効になっている場合にのみ影響します。最初のオペランドは文字列 llvm.loop.vectorize.scalable.enable であり、2番目のオペランドはビットです。ビットオペランド値が 1 の場合、スケーラブルなベクトル化が有効になります。値が 0 の場合は、デフォルトの固定幅ベクトル化に戻ります。

!0 = !{!"llvm.loop.vectorize.scalable.enable", i1 0}
!1 = !{!"llvm.loop.vectorize.scalable.enable", i1 1}

llvm.loop.vectorize.width’ メタデータ

このメタデータは、ベクタライザーのターゲット幅を設定します。最初のオペランドは文字列 llvm.loop.vectorize.width であり、2番目のオペランドは幅を指定する整数です。例えば

!0 = !{!"llvm.loop.vectorize.width", i32 4}

llvm.loop.vectorize.width を 1 に設定すると、ループのベクトル化が無効になることに注意してください。llvm.loop.vectorize.width が 0 に設定されている場合、またはループにこのメタデータがない場合、幅は自動的に決定されます。

llvm.loop.vectorize.followup_vectorized’ メタデータ

このメタデータは、ベクトル化されたループが持つループ属性を定義します。詳細については、コード変換メタデータを参照してください。

llvm.loop.vectorize.followup_epilogue’ メタデータ

このメタデータは、エピローグが持つループ属性を定義します。エピローグはベクトル化されず、ベクトル化されたループがセマンティクスを維持することがわかっていない場合(たとえば、実行時チェックによってエイリアスが見つかった2つの配列を処理する場合)、またはベクトルレーンの完全なセットを埋めない最後の反復の場合に実行されます。詳細については、変換メタデータを参照してください。

llvm.loop.vectorize.followup_all’ メタデータ

メタデータ内の属性は、ベクトル化されたループとエピローグループの両方に追加されます。詳細については、変換メタデータを参照してください。

llvm.loop.unroll

llvm.loop.unroll で始まるメタデータは、アンロールファクターなどのループアンロール最適化ヒントです。llvm.loop.unroll メタデータは、llvm.loop ループ識別メタデータと組み合わせて使用する必要があります。llvm.loop.unroll メタデータは最適化のヒントにすぎず、アンロールは、オプティマイザがそうすることが安全であると判断した場合にのみ実行されます。

llvm.loop.unroll.count’ メタデータ

このメタデータは、ループアンローラーへのアンロールファクターを提案します。最初のオペランドは文字列 llvm.loop.unroll.count であり、2番目のオペランドはアンロールファクターを指定する正の整数です。例えば

!0 = !{!"llvm.loop.unroll.count", i32 4}

ループのトリップカウントがアンロールカウントより小さい場合、ループは部分的にアンロールされます。

llvm.loop.unroll.disable’ メタデータ

このメタデータは、ループアンロールを無効にします。メタデータには、文字列 llvm.loop.unroll.disable である単一のオペランドがあります。例えば

!0 = !{!"llvm.loop.unroll.disable"}

llvm.loop.unroll.runtime.disable’ メタデータ

このメタデータは、ランタイムループアンロールを無効にします。メタデータには、文字列 llvm.loop.unroll.runtime.disable である単一のオペランドがあります。例えば

!0 = !{!"llvm.loop.unroll.runtime.disable"}

llvm.loop.unroll.enable’ メタデータ

このメタデータは、ループのトリップカウントがコンパイル時にわかっている場合はループを完全にアンロールし、トリップカウントがコンパイル時にわかっていない場合は部分的にアンロールすることを提案します。メタデータには、文字列 llvm.loop.unroll.enable である単一のオペランドがあります。例えば

!0 = !{!"llvm.loop.unroll.enable"}

llvm.loop.unroll.full’ メタデータ

このメタデータは、ループを完全にアンロールすることを提案します。メタデータには、文字列 llvm.loop.unroll.full である単一のオペランドがあります。例えば

!0 = !{!"llvm.loop.unroll.full"}

llvm.loop.unroll.followup’ メタデータ

このメタデータは、展開されたループが持つループ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.unroll.followup_remainder’ メタデータ

このメタデータは、部分展開/ランタイム展開後の剰余ループが持つループ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.unroll_and_jam

このメタデータは、上記の llvm.loop.unroll メタデータと非常に似ていますが、アンロールアンドジャムパスに影響を与えます。さらに、llvm.loop.unroll メタデータを持つが、llvm.loop.unroll_and_jam メタデータを持たないループは、アンロールアンドジャムを無効にします(したがって、llvm.loop.unroll メタデータはアンローラーに任され、さらに llvm.loop.unroll.disable メタデータもアンロールアンドジャムを無効にします)。

アンロールアンドジャムのメタデータは、それ以外は unroll と同じです。llvm.loop.unroll_and_jam.enablellvm.loop.unroll_and_jam.disable、および llvm.loop.unroll_and_jam.count はアンロールの場合と同じ動作をします。llvm.loop.unroll_and_jam.full はサポートされていません。繰り返しますが、これらは単なるヒントであり、通常の安全チェックは引き続き実行されます。

llvm.loop.unroll_and_jam.count’ メタデータ

このメタデータは、llvm.loop.unroll.count と同様に、使用するアンロールアンドジャムの係数を示唆します。最初のオペランドは文字列 llvm.loop.unroll_and_jam.count であり、2番目のオペランドはアンロール係数を指定する正の整数です。例:

!0 = !{!"llvm.loop.unroll_and_jam.count", i32 4}

ループのトリップカウントがアンロールカウントよりも小さい場合、ループは部分的にアンロールおよびジャムされます。

llvm.loop.unroll_and_jam.disable’ メタデータ

このメタデータは、ループのアンロールとジャムを無効にします。メタデータには、文字列 llvm.loop.unroll_and_jam.disable である単一のオペランドがあります。例:

!0 = !{!"llvm.loop.unroll_and_jam.disable"}

llvm.loop.unroll_and_jam.enable’ メタデータ

このメタデータは、ループのトリップカウントがコンパイル時にわかっている場合は完全にアンロールおよびジャムされ、トリップカウントがコンパイル時にわからない場合は部分的にアンロールされることを示唆します。メタデータには、文字列 llvm.loop.unroll_and_jam.enable である単一のオペランドがあります。例:

!0 = !{!"llvm.loop.unroll_and_jam.enable"}

llvm.loop.unroll_and_jam.followup_outer’ メタデータ

このメタデータは、外側の展開されたループが持つループ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.unroll_and_jam.followup_inner’ メタデータ

このメタデータは、内側のジャムされたループが持つループ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.unroll_and_jam.followup_remainder_outer’ メタデータ

このメタデータは、外側のループのエピローグが持つ属性を定義します。このループは通常アンロールされるため、そのようなループは存在しません。この属性は、この場合は無視されます。詳細については、変換メタデータを参照してください。

llvm.loop.unroll_and_jam.followup_remainder_inner’ メタデータ

このメタデータは、エピローグの内側のループが持つ属性を定義します。外側のエピローグは通常アンロールされるため、複数の内側の剰余ループが存在する可能性があります。詳細については、変換メタデータを参照してください。

llvm.loop.unroll_and_jam.followup_all’ メタデータ

メタデータで指定された属性は、すべての llvm.loop.unroll_and_jam.* ループに追加されます。詳細については、変換メタデータを参照してください。

llvm.loop.licm_versioning.disable’ メタデータ

このメタデータは、ループ不変コード移動(LICM)を有効にする目的で、ループをバージョン管理すべきでないことを示します。メタデータには、文字列 llvm.loop.licm_versioning.disable である単一のオペランドがあります。例:

!0 = !{!"llvm.loop.licm_versioning.disable"}

llvm.loop.distribute.enable’ メタデータ

ループ分散を使用すると、ループを複数のループに分割できます。現在、これは、安全でないメモリ依存関係のためにループ全体をベクトル化できない場合にのみ実行されます。この変換は、安全でない依存関係を独自のループに分離しようとします。

このメタデータを使用して、ループの分散を選択的に有効または無効にできます。最初のオペランドは文字列 llvm.loop.distribute.enable であり、2番目のオペランドはビットです。ビットオペランドの値が1の場合、分散が有効になります。値が0の場合は、分散が無効になります。

!0 = !{!"llvm.loop.distribute.enable", i1 0}
!1 = !{!"llvm.loop.distribute.enable", i1 1}

このメタデータは、llvm.loop ループ識別メタデータと組み合わせて使用する必要があります。

llvm.loop.distribute.followup_coincident’ メタデータ

このメタデータは、循環依存関係のない(つまり、ベクトル化可能な)抽出されたループが持つ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.distribute.followup_sequential’ メタデータ

このメタデータは、安全でないメモリ依存関係を持つ分離されたループが持つ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.distribute.followup_fallback’ メタデータ

ループのバージョン管理が必要な場合、このメタデータは、分散されていないフォールバックバージョンが持つ属性を定義します。詳細については、変換メタデータを参照してください。

llvm.loop.distribute.followup_all’ メタデータ

このメタデータの属性は、ループ分散パスのすべてのフォロアップループに追加されます。詳細については、変換メタデータを参照してください。

llvm.licm.disable’ メタデータ

このメタデータは、ループ不変コード移動(LICM)をこのループで実行すべきではないことを示します。メタデータには、文字列 llvm.licm.disable である単一のオペランドがあります。例:

!0 = !{!"llvm.licm.disable"}

ループごとに動作しますが、llvm.loop.disable_nonforced メタデータの影響を受けないため、llvm.loopプレフィックスは付与されないことに注意してください。

llvm.access.group’ メタデータ

llvm.access.group メタデータは、メモリにアクセスする可能性のある任意の命令にアタッチできます。これは、アクセスグループと呼ばれる単一の個別のメタデータノードを指すことができます。このノードは、llvm.access.group を介して参照するすべてのメモリアクセス命令を表します。命令が複数のアクセスグループに属している場合、次の例に示すように、アクセスグループのリストを指すこともできます。

%val = load i32, ptr %arrayidx, !llvm.access.group !0
...
!0 = !{!1, !2}
!1 = distinct !{}
!2 = distinct !{}

リストノードは、アクセスグループと混同される可能性があるため、空にすることは違法です。

アクセスグループメタデータノードは、コンテンツによって複数のアクセスグループが折りたたまれないように、「個別の」ものでなければなりません。アクセスグループメタデータノードは常に空である必要があり、これはアクセスグループメタデータノードをアクセスグループのリストと区別するために使用できます。空であることで、メタデータは設計上不変であるため、コンテンツを更新する必要がある状況を回避できます。これは、アクセスグループノードへのすべての参照を見つけて更新する必要があります。

アクセスグループは、(グローバルメタデータでは不可能な)直接ポイントせずにメモリアクセス命令を参照するために使用できます。現在、これを利用している唯一のメタデータは llvm.loop.parallel_accesses です。

llvm.loop.parallel_accesses’ メタデータ

llvm.loop.parallel_accesses メタデータは、1つ以上のアクセスグループメタデータノードを参照します(llvm.access.groupを参照)。これは、ループ内でこのメタデータを持つ他の命令との間にループ運搬メモリ依存関係が存在しないことを示します。

m1m2 を、それぞれアクセスグループ g1 および g2 (同じ場合もある)への llvm.access.group メタデータを持つ2つの命令とします。ループの llvm.loop.parallel_accesses メタデータに両方のアクセスグループが含まれている場合、コンパイラは、このループによって伝搬される m1m2 の間に依存関係がないと仮定できます。複数のアクセスグループに属する命令は、少なくとも1つのアクセスグループが llvm.loop.parallel_accesses リストに一致する場合、このプロパティを持つと見なされます。

ループ内のすべてのメモリアクセス命令が、ループの llvm.loop.parallel_accesses メタデータのアクセスグループのいずれかを参照する llvm.access.group メタデータを持っている場合、ループにはループ伝搬メモリー依存関係はなく、並列ループと見なされます。

すべてのメモリアクセス命令が llvm.loop.parallel_accesses で参照されるアクセスグループに属しているわけではない場合、ループは自明に並列とは見なされないことに注意してください。その判断を行うには、追加のメモリー依存関係分析が必要です。安全機構として、これにより、元々並列であったループが順次実行されると見なされます(並列セマンティクスを認識しない最適化パスが、新しいメモリー命令をループ本体に挿入する場合)。

llvm.access.group および llvm.loop.parallel_accesses メタデータ型を正しく使用することにより、並列と見なされるループの例。

for.body:
  ...
  %val0 = load i32, ptr %arrayidx, !llvm.access.group !1
  ...
  store i32 %val0, ptr %arrayidx1, !llvm.access.group !1
  ...
  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0

for.end:
...
!0 = distinct !{!0, !{!"llvm.loop.parallel_accesses", !1}}
!1 = distinct !{}

入れ子になった並列ループを持つことも可能です。

outer.for.body:
  ...
  %val1 = load i32, ptr %arrayidx3, !llvm.access.group !4
  ...
  br label %inner.for.body

inner.for.body:
  ...
  %val0 = load i32, ptr %arrayidx1, !llvm.access.group !3
  ...
  store i32 %val0, ptr %arrayidx2, !llvm.access.group !3
  ...
  br i1 %exitcond, label %inner.for.end, label %inner.for.body, !llvm.loop !1

inner.for.end:
  ...
  store i32 %val1, ptr %arrayidx4, !llvm.access.group !4
  ...
  br i1 %exitcond, label %outer.for.end, label %outer.for.body, !llvm.loop !2

outer.for.end:                                          ; preds = %for.body
...
!1 = distinct !{!1, !{!"llvm.loop.parallel_accesses", !3}}     ; metadata for the inner loop
!2 = distinct !{!2, !{!"llvm.loop.parallel_accesses", !3, !4}} ; metadata for the outer loop
!3 = distinct !{} ; access group for instructions in the inner loop (which are implicitly contained in outer loop as well)
!4 = distinct !{} ; access group for instructions in the outer, but not the inner loop

llvm.loop.mustprogress」メタデータ

llvm.loop.mustprogress メタデータは、このループが終了、アンワインド、または揮発性メモリアクセス、I/O、その他の同期などを介して、観察可能な方法で環境と相互作用する必要があることを示します。そのようなループが観察可能な方法で環境と相互作用することがわからなかった場合、ループは削除される可能性があります。これは、mustprogress 関数属性に対応します。

irr_loop」メタデータ

irr_loop メタデータは、非可約ループヘッダーである基本ブロックのターミネーター命令に付加される場合があります(非可約ループには複数のヘッダー基本ブロックがあることに注意してください)。irr_loop メタデータが、実際には非可約ループヘッダーではない基本ブロックのターミネーター命令に付加されている場合、動作は未定義です。このメタデータの目的は、ブロック頻度伝播の精度を向上させることです。たとえば、以下のコードでは、ブロック header0 は、100のループヘッダー重み(非可約ループの他のヘッダーに対する相対的な重み)を持つ可能性があります。

header0:
...
br i1 %cmp, label %t1, label %t2, !irr_loop !0

...
!0 = !{"loop_header_weight", i64 100}

非可約ループヘッダーの重みは、通常、プロファイルデータに基づいています。

invariant.group」メタデータ

試験的な invariant.group メタデータは、エントリのない単一のメタデータを参照する load/store 命令に付加される場合があります。命令の invariant.group メタデータの存在は、オプティマイザーに、同じポインターオペランドへのすべての load および store が同じ値をロードまたはストアすると仮定できることを伝えます(ただし、2つのポインターが同じと見なされるときに影響を与える llvm.launder.invariant.group 組み込み関数を参照してください)。ビットキャストまたはゼロインデックスのみを持つ getelementptr によって返されるポインターは同じと見なされます。

@unknownPtr = external global i8
...
%ptr = alloca i8
store i8 42, ptr %ptr, !invariant.group !0
call void @foo(ptr %ptr)

%a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
call void @foo(ptr %ptr)

%newPtr = call ptr @getPointer(ptr %ptr)
%c = load i8, ptr %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr

%unknownValue = load i8, ptr @unknownPtr
store i8 %unknownValue, ptr %ptr, !invariant.group !0 ; Can assume that %unknownValue == 42

call void @foo(ptr %ptr)
%newPtr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr)
%d = load i8, ptr %newPtr2, !invariant.group !0  ; Can't step through launder.invariant.group to get value of %ptr

...
declare void @foo(ptr)
declare ptr @getPointer(ptr)
declare ptr @llvm.launder.invariant.group.p0(ptr)

!0 = !{}

エイリアス情報に基づいてあるポインターを別のポインターに置き換えるときは、invariant.group メタデータを削除する必要があります。これは、invariant.group がポインターオペランドの SSA 値に関連付けられているためです。

%v = load i8, ptr %x, !invariant.group !0
; if %x mustalias %y then we can replace the above instruction with
%v = load i8, ptr %y

これは実験的な機能であり、そのセマンティクスは将来変更される可能性があることに注意してください。

type」メタデータ

型メタデータを参照してください。

associated」メタデータ

associated メタデータは、グローバルオブジェクト(必要に応じてエイリアス経由)を参照する単一の引数を持つグローバル変数定義に付加される場合があります。

このメタデータは、ELFセクションフラグ SHF_LINK_ORDER に変換されます。これにより、参照されるオブジェクトも破棄されない限り、リンカーGCでグローバル変数が破棄されるのを防ぎます。この機能のリンカーサポートは不安定です。最適な互換性のために、このメタデータを持つグローバル変数は、次のようである必要があります。

  • @llvm.compiler.used にある。

  • 参照されるグローバル変数がcomdatにある場合、同じcomdatにある。

!associated は多対一の関係を表すことはできません。メタデータを持つグローバル変数は、一般に関数によって参照されるべきではありません。関数は他の関数にインライン化される可能性があり、メタデータへの参照が増えることになります。理想的には、インラインの場所が生きている限りメタデータを維持したいのですが、この多対一の関係は表現できません。さらに、関数が破棄されている間にメタデータが保持されている場合、リンカーは破棄されたセクションを参照する再配置のエラーを報告します。

メタデータは、ランタイムがリンカー定義のカプセル化シンボル __start_<section_name> および __stop_<section_name> を使用してメタデータセクションを見つけることができるように、有効なC識別子で構成される明示的なセクションでよく使用されます。

非ELFターゲットには影響しません。

$a = comdat any
@a = global i32 1, comdat $a
@b = internal global i32 2, comdat $a, section "abc", !associated !0
!0 = !{ptr @a}

prof」メタデータ

prof メタデータは、IRにプロファイルデータを記録するために使用されます。メタデータノードの最初のオペランドは、プロファイルメタデータ型を示します。現在、branch_weightsfunction_entry_countVP の3つの型があります。

branch_weights

分岐、select、switch、またはcall命令に付加された分岐重みメタデータは、関連付けられた分岐が取られる可能性を表します。詳細については、LLVM分岐重みメタデータを参照してください。

function_entry_count

関数エントリカウントメタデータは、関数が呼び出された回数を記録するために、関数定義に付加できます。BFI情報とともに使用して、基本ブロックのプロファイルカウントを導出するためにも使用されます。詳細については、LLVM分岐重みメタデータを参照してください。

VP

VP(値プロファイル)メタデータは、値プロファイル情報を持つ命令に付加できます。現在、これは間接呼び出し(最もホットな呼び出し先を記録)と、memcpy、memmove、memsetなどのメモリ組み込み関数への呼び出し(最もホットなバイト長を記録)です。

各VPメタデータノードには、「VP」文字列、次に値プロファイルの種類を示すuint32_t値、命令が実行された合計回数を示すuint64_t値、その後にuint64_t値と実行カウントのペアが含まれています。値プロファイルの種類は、間接呼び出しターゲットの場合は0、メモリ操作の場合は1です。間接呼び出しターゲットの場合、各プロファイル値は呼び出し先関数名のハッシュであり、メモリ操作の場合、各値はバイト長です。

値カウントは、3番目のオペランドにリストされている合計カウントに加算する必要はないことに注意してください(実際には、最もホットな上位の値のみが追跡および報告されます)。

間接呼び出しの例

call void %f(), !prof !1
!1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410}

VP型は0(2番目のオペランド)であることに注意してください。これは、間接呼び出しの値プロファイルデータであることを示しています。3番目のオペランドは、間接呼び出しが1600回実行されたことを示しています。4番目と6番目のオペランドは、最もホットな2つのターゲット関数の名前のハッシュ(これはプロファイルデータベースで関数名を表すために使用されるのと同じハッシュ)を示し、5番目と7番目のオペランドは、それぞれの前のターゲット関数が呼び出された実行カウントを示します。

annotation」メタデータ

annotation メタデータは、注釈文字列のタプルまたは注釈文字列のタプルを任意の命令に付加するために使用できます。このメタデータはプログラムのセマンティクスに影響を与えず、プログラムやユーザーへの変換に関する追加の洞察を提供するためのみに使用できます。

%a.addr = alloca ptr, align 8, !annotation !0
!0 = !{!"auto-init"}

文字列のタプルの埋め込み例

%a.ptr = getelementptr ptr, ptr %base, i64 0. !annotation !0
!0 = !{!1}
!1 = !{!"gep offset", !"0"}

func_sanitize」メタデータ

func_sanitize メタデータは、関数サニタイザーのインストルメンテーションのために2つの値を付加するために使用されます。最初の値はubsan関数シグネチャです。2番目の値は、RTTI記述子のアドレスを格納するプロキシ変数のアドレスです。プロローグと「func_sanitize」が同時に使用される場合、出力ではプロローグが「func_sanitize」よりも前に出力されます。

@__llvm_rtti_proxy = private unnamed_addr constant ptr @_ZTIFvvE
define void @_Z3funv() !func_sanitize !0 {
  return void
}
!0 = !{i32 846595819, ptr @__llvm_rtti_proxy}

kcfi_type」メタデータ

kcfi_type メタデータは、間接的に呼び出すことができる関数に型識別子を付加するために使用できます。型データはアセンブリ内の関数エントリの前に出力されます。kcfiオペランドバンドルを使用した間接呼び出しは、型識別子をメタデータと比較するチェックを出力します。

define dso_local i32 @f() !kcfi_type !0 {
  ret i32 0
}
!0 = !{i32 12345678}

Clangは、-fsanitize=kcfi を使用してアドレス取得された関数に対して kcfi_type メタデータノードを出力します。

memprof」メタデータ

memprof メタデータは、ヒープ割り当て呼び出しに関するメモリプロファイルデータを記録するために使用されます。複数のコンテキスト依存のプロファイルは、単一の memprof メタデータアタッチメントで表すことができます。

%call = call ptr @_Znam(i64 10), !memprof !0, !callsite !5
!0 = !{!1, !3}
!1 = !{!2, !"cold"}
!2 = !{i64 4854880825882961848, i64 1905834578520680781}
!3 = !{!4, !"notcold"}
!4 = !{i64 4854880825882961848, i64 -6528110295079665978}
!5 = !{i64 4854880825882961848}

memprof メタデータアタッチメントの各オペランドは、特定のコンテキストにおける関連する割り当てによって割り当てられたメモリのプロファイルされた動作を記述します。上記の例では、プロファイルされたコンテキストが2つあり、1つは通常コールドであるメモリを割り当て、もう1つは通常コールドでないメモリを割り当てています。

コンテキスト固有のプロファイルを記述するメタデータの形式(上記の例の!1!3など)では、最初のオペランドはコンテキストを記述するメタデータノードであり、その後にプロファイル動作を記述する文字列メタデータタグのリスト(上記の例のcoldnotcoldなど)が続きます。コンテキストを記述するメタデータノード(上記の例の!2!4など)は、コールサイトに対応する一意のIDであり、コールサイトメタデータを介して関連するIR呼び出しと照合できます。実際には、これらのIDはコールサイトのデバッグ情報のハッシュを介して形成され、関連する呼び出しは異なるモジュールにある場合があります。コンテキストは、最もリーフ側の呼び出し(割り当て自体)から、記述されたプロファイル動作を一意に識別するために必要な最も外側のコールサイトコンテキストまで(プロファイルされたコールスタックの最上部ではない場合があることに注意)、順番にリストされます。

callsite」メタデータ

callsite メタデータは、memprofメタデータで記述されているメモリプロファイルコンテキストに関与するコールサイトを識別するために使用されます。

これは、プロファイル割り当て呼び出し(memprofメタデータの例を参照)と、ヒープ割り当てmemprofメタデータで記述されているプロファイルされたコンテキストの他のコールサイトの両方にアタッチされます。

%call = call ptr @_Z1Bb(void), !callsite !0
!0 = !{i64 -6528110295079665978, i64 5462047985461644151}

callsite メタデータアタッチメントの各オペランドは、コールサイトに対応する一意のIDです(インライン化されている可能性があります)。実際には、これらのIDはコールサイトのデバッグ情報のハッシュを介して形成されます。呼び出しがどの呼び出し元にもインライン化されていない場合は、単一のオペランド(ID)が含まれます。インライン化されている場合は、最もリーフ側の呼び出しのIDから最も外側のインライン化された呼び出しまで、完全なインラインシーケンス内のコールサイトのIDを含むIDのリストが含まれます。

モジュールフラグメタデータ

モジュール全体に関する情報をLLVMのサブシステムに伝達するのは困難です。LLVM IRはこの情報を伝達するのに十分ではありません。これを容易にするために、llvm.module.flagsという名前付きメタデータが存在します。これらのフラグはキーと値のペアの形式であり、辞書のように、フラグに関心のあるサブシステムが簡単に検索できます。

llvm.module.flags メタデータには、メタデータトリプレットのリストが含まれています。各トリプレットは次の形式になります。

  • 最初の要素は動作フラグであり、2つ(またはそれ以上)のモジュールがマージされたときに、同じIDを持つ2つ(またはそれ以上)のメタデータが検出された場合の動作を指定します。サポートされている動作については以下で説明します。

  • 2番目の要素は、メタデータの一意のIDであるメタデータ文字列です。各モジュールには、一意のIDごとに1つのフラグエントリのみを含めることができます(Require動作のエントリは含まれません)。

  • 3番目の要素は、フラグの値です。

2つ(またはそれ以上)のモジュールがマージされると、結果の llvm.module.flags メタデータは、モジュールのフラグの和集合になります。つまり、一意のメタデータID文字列ごとに、マージされたモジュールの llvm.module.flags メタデータテーブルに正確に1つのエントリが存在し、そのエントリの値は、以下で説明するように、マージ動作フラグによって決定されます。唯一の例外は、Require動作のエントリは常に保持されることです。

以下の動作がサポートされています。

動作

1

エラー

2つの値が一致しない場合はエラーを生成します。それ以外の場合、結果の値はオペランドの値になります。

2

警告

2つの値が一致しない場合は警告を生成します。結果の値は、他のモジュールがMinまたはMaxを使用していない限り、リンクされている最初のモジュールからのフラグのオペランドになります。その場合、結果はそれぞれMin(最小値)またはMax(最大値)になります。

3

必要

別のモジュールフラグが存在し、リンクが実行された後に指定された値を持つという要件を追加します。値はメタデータのペアである必要があり、ペアの最初の要素は制限されるモジュールフラグのIDであり、ペアの2番目の要素はモジュールフラグが制限される値である必要があります。この動作は、Override動作でIDをリンクすることによる許容される結果を制限するために使用できます(エラーのトリガーを介して)。

4

上書き

他のモジュールの動作や値に関係なく、指定された値を使用します。両方のモジュールがOverrideを指定しているが、値が異なる場合は、エラーが生成されます。

5

追加

2つの値を追加します。これはメタデータノードである必要があります。

6

一意に追加

2つの値を追加します。これはメタデータノードである必要があります。ただし、2番目のリストの重複エントリは、追加操作中に削除されます。

7

最大

2つの値の最大値を取得します。これは整数である必要があります。

8

最小

2つの値の最小値を取得します。これは非負の整数である必要があります。存在しないモジュールフラグは、値0を持つものとして扱われます。

特定のユニークなフラグIDが複数の動作を持つことは、Require(別のメタデータ値に制限を追加します)またはOverrideの場合を除いて、エラーになります。

モジュールフラグの例

!0 = !{ i32 1, !"foo", i32 1 }
!1 = !{ i32 4, !"bar", i32 37 }
!2 = !{ i32 2, !"qux", i32 42 }
!3 = !{ i32 3, !"qux",
  !{
    !"foo", i32 1
  }
}
!llvm.module.flags = !{ !0, !1, !2, !3 }
  • メタデータ !0 はID !"foo" と値 ‘1’ を持ちます。2つ以上の !"foo" フラグが見られた場合の動作は、それらの値が等しくない場合にエラーを生成することです。

  • メタデータ !1 はID !"bar" と値 ‘37’ を持ちます。2つ以上の !"bar" フラグが見られた場合の動作は、値 ‘37’ を使用することです。

  • メタデータ !2 はID !"qux" と値 ‘42’ を持ちます。2つ以上の !"qux" フラグが見られた場合の動作は、それらの値が等しくない場合に警告を生成することです。

  • メタデータ !3 はID !"qux" と値

    !{ !"foo", i32 1 }
    

    動作は、リンクが実行された後に、llvm.module.flags にID !"foo" を持ち、値 ‘1’ を持つフラグが含まれていない場合にエラーを生成することです。

合成された関数モジュールフラグメタデータ

これらのメタデータは、合成された関数が持つべきデフォルト属性を指定します。これらのメタデータは現在、サニタイザーなど、いくつかのインストルメンテーションパスで尊重されています。

これらのメタデータは、重要なコード生成動作を持ついくつかの関数属性に対応します。最適化のみを目的とする関数属性は、これらの合成関数のパフォーマンスへの影響が小さいため、リストしないでください。

  • 「frame-pointer」:最大。値は0、1、または2にすることができます。合成された関数は、「frame-pointer」関数属性を取得し、値はそれぞれ「none」、「non-leaf」、または「all」になります。

  • 「function_return_thunk_extern」:合成された関数は、fn_return_thunk_extern 関数属性を取得します。

  • 「uwtable」:最大。値は0、1、または2にすることができます。値が1の場合、合成された関数はuwtable(sync)関数属性を取得し、値が2の場合、合成された関数はuwtable(async)関数属性を取得します。

Objective-Cガベージコレクションモジュールフラグメタデータ

Mach-Oプラットフォームでは、Objective-Cはガベージコレクションに関するメタデータを「image info」という特別なセクションに格納します。メタデータは、バージョン番号と、ファイルがサポートする(もしあれば)ガベージコレクションのタイプを指定するビットマスクで構成されます。複数のモジュールがリンクされる場合、それらのガベージコレクションメタデータは、単に連結するのではなく、マージする必要があります。

Objective-Cのガベージコレクションモジュールフラグメタデータは、次のキーと値のペアで構成されます。

キー

Objective-C Version

[必須] — Objective-C ABIのバージョン。有効な値は1と2です。

Objective-C Image Info Version

[必須] — image infoセクションのバージョン。現在、常に0です。

Objective-C Image Info Section

[必須] — メタデータを配置するセクション。有効な値は、Objective-C ABIバージョン1の場合"__OBJC, __image_info, regular"、Objective-C ABIバージョン2の場合"__DATA,__objc_imageinfo, regular, no_dead_strip"です。

Objective-C Garbage Collection

[必須] — ガベージコレクションがサポートされているかどうかを指定します。有効な値は、ガベージコレクションをサポートしない場合は0、ガベージコレクションをサポートする場合は2です。

Objective-C GC Only

[オプション] — ガベージコレクションのみがサポートされていることを指定します。存在する場合、その値は6でなければなりません。このフラグには、Objective-C Garbage Collectionフラグの値が2である必要があります。

いくつかの重要なフラグの相互作用

  • Objective-C Garbage Collectionが0に設定されているモジュールが、Objective-C Garbage Collectionが2に設定されているモジュールとマージされた場合、結果のモジュールではObjective-C Garbage Collectionフラグが0に設定されます。

  • Objective-C Garbage Collectionが0に設定されているモジュールは、Objective-C GC Onlyが6に設定されているモジュールとマージできません。

C型幅モジュールフラグメタデータ

ARMバックエンドは、コンパイルされたオプションを記述するセクションを生成された各オブジェクトファイルに出力します(コンパイラに依存しない方法で)。これは、互換性のないオブジェクトのリンクを防止し、自動ライブラリ選択を可能にするためです。これらのオプションの中には、IRレベルでは見えないものがあり、具体的にはwchar_tの幅とenumの幅です。

この情報をバックエンドに渡すために、これらのオプションは、次のキーと値のペアを使用して、モジュールフラグメタデータにエンコードされます。

キー

short_wchar

  • 0 — sizeof(wchar_t) == 4

  • 1 — sizeof(wchar_t) == 2

short_enum

  • 0 — 列挙型は、少なくともintと同じ大きさです。

  • 1 — 列挙型は、そのすべての値を表現できる最小の整数型に格納されます。

たとえば、次のメタデータセクションは、モジュールが4バイトのwchar_t幅でコンパイルされ、列挙型の基本型がそのすべての値を表現できる最小の型であることを指定しています。

!llvm.module.flags = !{!0, !1}
!0 = !{i32 1, !"short_wchar", i32 1}
!1 = !{i32 1, !"short_enum", i32 0}

スタックアライメントメタデータ

ターゲットABIの暗黙的なデフォルトスタックアライメントからデフォルトのスタックアライメントを変更します。バイト単位でi32の値を取ります。このメタデータの値が異なる2つのモジュールをリンクすると、エラーと見なされます。

例:

!llvm.module.flags = !{!0} !0 = !{i32 1, !”override-stack-alignment”, i32 8}

これにより、スタックアライメントが8Bに変更されます。

埋め込みオブジェクト名メタデータ

オフロードコンパイルでは、ファットバイナリを作成するためにデバイスコードをホストセクションテーブルに埋め込む必要があります。このメタデータノードは、モジュールに埋め込まれる各グローバルを参照します。これの主な用途は、IRでのこれらのグローバルへの参照をより効率的にすることです。メタデータは、埋め込まれるグローバルへのポインタと、それが格納されるセクション名を含むノードを参照します。

!llvm.embedded.objects = !{!0}
!0 = !{ptr @object, !".section"}

自動リンカフラグ名前付きメタデータ

一部のターゲットは、個々のオブジェクトファイル内にリンカへのフラグの埋め込みをサポートしています。通常、これは、ソースファイルにリンカのコマンドラインオプションを含めることを許可し、これらのオプションをオブジェクトファイルを介してリンカに自動的に送信させる言語拡張機能と組み合わせて使用されます。

これらのフラグは、名前が!llvm.linker.optionsの名前付きメタデータを使用してIRにエンコードされます。各オペランドはメタデータノードであると想定されており、これは他のメタデータノードのリストである必要があり、各ノードはリンカオプションを定義するメタデータ文字列のリストである必要があります。

たとえば、次のメタデータセクションは、libzおよびCocoaフレームワークに対してリンクするための2つの異なるリンカオプションセットを指定しています。

!0 = !{ !"-lz" }
!1 = !{ !"-framework", !"Cocoa" }
!llvm.linker.options = !{ !0, !1 }

オプションのリストのリストとしてのメタデータエンコーディングは、オプションの折りたたまれたリストとは対照的に、IRエンコーディングが、たとえば、単一のライブラリを指定するために複数のオプション文字列を使用できるようにするために選択されていますが、その指定子をターゲット固有のアセンブリライターまたはオブジェクトファイルエミッタによって認識できるアトミック要素として保持できるようにしています。

個々のオプションは、ターゲットのリンカの有効なオプションであるか、ターゲット固有のアセンブリライターまたはオブジェクトファイルエミッタによって予約されているオプションである必要があります。これらのオプションの他の側面は、IRによって定義されていません。

依存ライブラリ名前付きメタデータ

一部のターゲットは、リンクに追加するライブラリのセットを示すために、オブジェクトファイルに文字列を埋め込むことをサポートしています。通常、これは、ソースファイルが依存するライブラリを明示的に宣言し、これらのライブラリをオブジェクトファイルを介してリンカに自動的に送信させる言語拡張機能と組み合わせて使用されます。

リストは、名前が!llvm.dependent-librariesの名前付きメタデータを使用してIRにエンコードされます。各オペランドはメタデータノードであると想定されており、これには単一の文字列オペランドが含まれている必要があります。

たとえば、次のメタデータセクションには2つのライブラリ指定子が含まれています

!0 = !{!"a library specifier"}
!1 = !{!"another library specifier"}
!llvm.dependent-libraries = !{ !0, !1 }

各ライブラリ指定子は、使用するリンカによって独立して処理されます。ライブラリ指定子の効果は、使用するリンカによって定義されます。

ThinLTOサマリー

ThinLTOでコンパイルすると、ビットコードに出力されるモジュールのコンパクトなサマリーが作成されます。サマリーはLLVMアセンブリに出力され、カレット(「^」)で構文的に識別されます。

サマリーは、モジュールIRとともに、「llvm-as」ツールを介してビットコード出力に解析されます。最適化を目的としてモジュールIRを解析するツール(例:「clang -x ir」および「opt」)は、サマリーエントリを無視します(ビットコード入力ファイル内のサマリーエントリを現在無視するのと同様)。

最終的に、サマリーは、サマリーインデックスが現在ビットコードから構築されるのと同じ条件下で、ModuleSummaryIndexオブジェクトに解析されます。具体的には、ThinLTOコンパイルのシンリンク部分をテストするツール(つまり、llvm-ltoとllvm-lto2)、またはclangの「-fthinlto-index=<>」フラグを介した分散ThinLTOバックエンドの結合インデックスを解析する場合(この部分はまだ実装されていません。当面は、シンリンクツールにフィードする前にllvm-asを使用してビットコードオブジェクトを作成してください)。

現在、LLVMアセンブリには、モジュールパスグローバル値、および型識別子の3種類のサマリーエントリがあります。

モジュールパスサマリーエントリ

各モジュールパスサマリーエントリは、サマリーに含まれるグローバル値を含むモジュールを一覧表示します。単一のIRモジュールの場合、このようなエントリは1つになりますが、シンリンク中に生成された結合サマリーインデックスでは、サマリーを持つリンクされたモジュールごとに1つのモジュールパスエントリが存在します。

^0 = module: (path: "/path/to/file.o", hash: (2468601609, 1329373163, 1565878005, 638838075, 3148790418))

pathフィールドはビットコードファイルへの文字列パスであり、hashフィールドは、インクリメンタルビルドとキャッシュに使用されるIRビットコードコンテンツの160ビットSHA-1ハッシュです。

グローバル値サマリーエントリ

各グローバル値サマリーエントリは、サマライズされたモジュールによって定義または参照されるグローバル値に対応します。

^4 = gv: (name: "f"[, summaries: (Summary)[, (Summary)]*]?) ; guid = 14740650423002898831

宣言の場合、サマリーリストはありません。定義の場合、グローバル値には、定義を含むモジュールごとに1つのサマリーのリストが含まれます。弱リンクを持つシンボルの結合サマリーインデックスには、複数のエントリが存在する可能性があります。

Summaryの形式は、グローバル値が関数変数、またはエイリアスのいずれであるかによって異なります。

関数の概要

グローバル値が関数の場合、Summaryエントリは次のようになります。

function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 2[, FuncFlags]?[, Calls]?[, TypeIdInfo]?[, Params]?[, Refs]?

moduleフィールドには、この定義を含むモジュールの概要エントリIDが含まれており、flagsフィールドには、リンケージタイプ、定義をインポートすることが合法であるかどうかを示すフラグ、グローバルにライブであるかどうか、リンカーがローカル定義に解決したかどうか(後者の2つはシンリンク中に設定されます)などの情報が含まれています。instsフィールドには、関数内のIR命令の数が含まれています。最後に、いくつかのオプションフィールドがあります:FuncFlagsCallsTypeIdInfoParamsRefs

グローバル変数の概要

グローバル値が変数の場合、Summaryエントリは次のようになります。

variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0)[, Refs]?

変数エントリには、関数の概要のフィールドのサブセットが含まれています。そちらの説明を参照してください。

エイリアスの概要

グローバル値がエイリアスの場合、Summaryエントリは次のようになります。

alias: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), aliasee: ^2)

moduleおよびflagsフィールドは、関数の概要の説明と同じです。aliaseeフィールドには、エイリアスのグローバル値の概要エントリへの参照が含まれています。

関数のフラグ

オプションのFuncFlagsフィールドは次のようになります。

funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0)

指定されていない場合、フラグは保守的なfalse値の0を保持すると想定されます。

呼び出し

オプションのCallsフィールドは次のようになります。

calls: ((Callee)[, (Callee)]*)

ここで、各Calleeは次のようになります。

callee: ^1[, hotness: None]?[, relbf: 0]?

calleeは、呼び出し先の概要エントリIDを参照します。hotnessUnknownColdNoneHot、およびCriticalの値を取ることができます)とrelbf(エントリ頻度に対して相対的な整数ブランチ頻度を保持し、2^8でスケールダウンされます)のいずれか1つが指定できます。デフォルトはそれぞれUnknown0です。

パラメータ

オプションのParamsは、StackSafetyによって使用され、次のようになります。

Params: ((Param)[, (Param)]*)

ここで、各Paramは、関数内のポインタパラメータアクセスを記述し、次のようになります。

param: 4, offset: [0, 5][, calls: ((Callee)[, (Callee)]*)]?

ここで、最初のparamはそれが記述するパラメータの数であり、offsetは関数がアクセスできるポインタパラメータからバイトへのオフセットの包括的な範囲です。この範囲には、callsリストからの関数呼び出しによるアクセスは含まれません。

ここで、各Calleeは、パラメータが他の関数にどのように転送されるかを記述し、次のようになります。

callee: ^3, param: 5, offset: [-3, 3]

calleeは、呼び出し先の概要エントリIDを参照し、paramは、offset範囲内であることがわかっているオフセットで、呼び出し元のパラメータを指す呼び出し先のパラメータの数です。callsは、シンリンク段階で消費および削除され、Param::offsetを更新して、callsによって可能なすべてのアクセスをカバーします。

対応するParamのないポインタパラメータは安全でないと見なされ、任意のオフセットでのアクセスが可能であると想定します。

次の関数がある場合

define i64 @foo(ptr %0, ptr %1, ptr %2, i8 %3) {
  store ptr %1, ptr @x
  %5 = getelementptr inbounds i8, ptr %2, i64 5
  %6 = load i8, ptr %5
  %7 = getelementptr inbounds i8, ptr %2, i8 %3
  tail call void @bar(i8 %3, ptr %7)
  %8 = load i64, ptr %0
  ret i64 %8
}

次のようなレコードが期待できます。

params: ((param: 0, offset: [0, 7]),(param: 2, offset: [5, 5], calls: ((callee: ^3, param: 1, offset: [-128, 127]))))

関数は、パラメータ%0の8バイトにのみアクセスできます。callsは空であるため、パラメータは関数呼び出しに使用されないか、offsetが既にネストされた関数呼び出しからのすべてのアクセスをカバーしています。パラメータ%1はエスケープするため、アクセスは不明です。関数自体は、パラメータ%2の単一のバイトにのみアクセスできます。追加のアクセスは、@barまたは^3内部で可能です。関数は、ポインタに符号付きオフセットを追加し、結果を^3の引数%1として渡します。このレコード自体は、^3がパラメータにどのようにアクセスするかを示していません。パラメータ%3はポインタではありません。

参照

オプションのRefsフィールドは次のようになります。

refs: ((Ref)[, (Ref)]*)

ここで、各Refには、参照された値(例:^1)の概要IDへの参照が含まれています。

TypeIdInfo

オプションのTypeIdInfoフィールドは、制御フローの整合性に使用され、次のようになります。

typeIdInfo: [(TypeTests)]?[, (TypeTestAssumeVCalls)]?[, (TypeCheckedLoadVCalls)]?[, (TypeTestAssumeConstVCalls)]?[, (TypeCheckedLoadConstVCalls)]?

これらのオプションフィールドには、次の形式があります。

TypeTests
typeTests: (TypeIdRef[, TypeIdRef]*)

ここで、各TypeIdRefは、概要IDまたはGUIDによる型IDを参照します。

TypeTestAssumeVCalls
typeTestAssumeVCalls: (VFuncId[, VFuncId]*)

ここで、各VFuncIdの形式は次のとおりです。

vFuncId: (TypeIdRef, offset: 16)

ここで、各TypeIdRefは、概要IDまたはguid:タグが付いたGUIDによる型IDを参照します。

TypeCheckedLoadVCalls
typeCheckedLoadVCalls: (VFuncId[, VFuncId]*)

ここで、各VFuncIdの形式は、TypeTestAssumeVCallsで説明されている形式です。

TypeTestAssumeConstVCalls
typeTestAssumeConstVCalls: (ConstVCall[, ConstVCall]*)

ここで、各ConstVCallの形式は次のとおりです。

(VFuncId, args: (Arg[, Arg]*))

各VFuncIdの形式はTypeTestAssumeVCallsで説明されており、各Argは整数引数番号です。

TypeCheckedLoadConstVCalls
typeCheckedLoadConstVCalls: (ConstVCall[, ConstVCall]*)

ここで、各ConstVCallの形式はTypeTestAssumeConstVCallsで説明されている形式です。

型IDの概要エントリ

各型IDの概要エントリは、制御フローの整合性を使用して構築する場合にコンパイルのLTOリンク部分で生成される型識別子解決に対応するため、これらは結合された概要インデックスにのみ存在します。

^4 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7[, alignLog2: 0]?[, sizeM1: 0]?[, bitMask: 0]?[, inlineBits: 0]?)[, WpdResolutions]?)) ; guid = 7004155349499253778

typeTestResは、型テスト解決のkindunsatbyteArrayinlinesingle、またはallOnesの場合があります)とsize-1ビット幅を指定します。それに続いて、デフォルトで0になるオプションのフラグと、次のようなオプションのWpdResolutions(プログラム全体の非仮想化解決)フィールドがあります。

wpdResolutions: ((offset: 0, WpdRes)[, (offset: 1, WpdRes)]*

ここで、各エントリは、指定されたバイトオフセットから、次のいずれかの形式を持つプログラム全体の非仮想化解決WpdResへのマッピングです。

wpdRes: (kind: branchFunnel)
wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")
wpdRes: (kind: indir)

さらに、各wpdResには、オプションのresByArgフィールドがあり、すべての定数整数引数を持つ呼び出しの解決を記述します。

resByArg: (ResByArg[, ResByArg]*)

ここで、ResByArgは次のようになります。

args: (Arg[, Arg]*), byArg: (kind: UniformRetVal[, info: 0][, byte: 0][, bit: 0])

ここで、kindは、IndirUniformRetValUniqueRetVal、またはVirtualConstPropにすることができます。infoフィールドは、kindがUniformRetVal(均一な戻り値を示す)またはUniqueRetVal(一意のvtableに関連付けられた戻り値を保持する(0または1))の場合にのみ使用されます。byteおよびbitフィールドは、ターゲットが定数を格納するために絶対シンボルの使用をサポートしていない場合にのみ使用されます。

組み込みグローバル変数

LLVMには、コード生成やその他のIRセマンティクスに影響を与えるデータを含む、いくつかの「マジック」グローバル変数があります。これらについてはここに文書化されています。この種のすべてのグローバル変数は、「llvm.metadata」として指定されたセクションを持つ必要があります。このセクションと「llvm.」で始まるすべてのグローバル変数は、LLVMで使用するために予約されています。

llvm.used’ グローバル変数

@llvm.usedグローバル変数は、追加リンケージを持つ配列です。この配列には、名前付きグローバル変数、関数、およびエイリアスへのポインタのリストが含まれており、それらはオプションでbitcastまたはgetelementptrで形成されたポインタキャストを持つことができます。たとえば、合法的な使用例は次のとおりです。

@X = global i8 4
@Y = global i32 123

@llvm.used = appending global [2 x ptr] [
   ptr @X,
   ptr @Y
], section "llvm.metadata"

シンボルが@llvm.usedリストに現れる場合、コンパイラ、アセンブラ、およびリンカは、そのシンボルに対して、見えない参照があるかのように扱う必要があります(そのため、名前付きである必要があります)。たとえば、変数が内部リンケージを持ち、@llvm.usedリストからの参照しかない場合、削除することはできません。これは通常、インラインアセンブラやコンパイラが「見ることができない」その他のものからの参照を表すために使用され、GNU Cの「attribute((used))」に対応します。

一部のターゲットでは、コードジェネレータは、アセンブラとリンカがシンボルを削除しないように、アセンブラまたはオブジェクトファイルに指示を出す必要があります。

llvm.compiler.used’ グローバル変数

@llvm.compiler.usedディレクティブは、コンパイラがシンボルに触れるのを防ぐ点を除いて、@llvm.usedディレクティブと同じです。それをサポートするターゲットでは、これにより、インテリジェントなリンカが@llvm.usedによって妨げられることなく、シンボルへの参照を最適化できます。

これはまれな構成であり、まれな状況でのみ使用する必要があり、ソース言語に公開されるべきではありません。

llvm.global_ctors’ グローバル変数

%0 = type { i32, ptr, ptr }
@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, ptr @ctor, ptr @data }]

@llvm.global_ctors配列には、コンストラクタ関数、優先度、および関連付けられたグローバル変数または関数のリストが含まれています。この配列で参照される関数は、モジュールがロードされるときに、優先度の昇順(つまり、最も低いものが最初)で呼び出されます。同じ優先度を持つ関数の順序は定義されていません。

3番目のフィールドがnullではなく、グローバル変数または関数を指している場合、初期化関数は、現在のモジュールからの関連データが破棄されない場合にのみ実行されます。ELFでは、参照されるグローバル変数または関数はcomdatにある必要があります。

llvm.global_dtors’ グローバル変数

%0 = type { i32, ptr, ptr }
@llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, ptr @dtor, ptr @data }]

@llvm.global_dtors配列には、デストラクタ関数、優先度、および関連付けられたグローバル変数または関数のリストが含まれています。この配列で参照される関数は、モジュールがアンロードされるときに、優先度の降順(つまり、最も高いものが最初)で呼び出されます。同じ優先度を持つ関数の順序は定義されていません。

3番目のフィールドがnullではなく、グローバル変数または関数を指している場合、デストラクタ関数は、現在のモジュールからの関連データが破棄されない場合にのみ実行されます。ELFでは、参照されるグローバル変数または関数はcomdatにある必要があります。

命令リファレンス

LLVM命令セットは、いくつかの異なる命令分類で構成されています:ターミネータ命令バイナリ命令ビット単位バイナリ命令メモリアクセス命令、およびその他の命令。また、デバッグレコードもあります。これは命令自体ではありませんが、プログラムの実行における各位置でのプログラムのデバッグ情報の状態の変化を記述するために、命令とインターリーブして出力されます。

ターミネータ命令

前述したように、プログラム内のすべての基本ブロックは「ターミネータ」命令で終わります。これは、現在のブロックの完了後にどのブロックを実行する必要があるかを示します。これらのターミネータ命令は通常、「void」値を生成します。つまり、値ではなく制御フローを生成します(唯一の例外は「invoke」命令です)。

ターミネータ命令は、「ret」、「br」、「switch」、「indirectbr」、「invoke」、「callbr」、「resume」、「catchswitch」、「catchret」、「cleanupret」、および「unreachable」です。

ret’ 命令

構文:
ret <type> <value>       ; Return a value from a non-void function
ret void                 ; Return from void function
概要:

ret」命令は、関数の制御フロー(およびオプションで値)を呼び出し元に戻すために使用されます。

ret」命令には、値を返して制御フローを発生させる形式と、制御フローのみを発生させる形式の2つがあります。

引数:

ret」命令はオプションで、戻り値である単一の引数を受け入れます。戻り値の型は「ファーストクラス」型である必要があります。

関数が非void戻り型を持ち、戻り値のない「ret」命令、または型が一致しない戻り値を持つ「ret」命令を含む場合、またはvoid戻り型を持ち、戻り値を持つ「ret」命令を含む場合は、整形式ではありません。

セマンティクス:

ret」命令が実行されると、制御フローは呼び出し元の関数のコンテキストに戻ります。呼び出し元が「call」命令の場合、実行はcallの後の命令から続行されます。呼び出し元が「invoke」命令の場合、実行は「通常」の宛先ブロックの先頭から続行されます。命令が値を返す場合、その値はcallまたはinvoke命令の戻り値を設定する必要があります。

例:
ret i32 5                       ; Return an integer value of 5
ret void                        ; Return from a void function
ret { i32, i8 } { i32 4, i8 2 } ; Return a struct of values 4 and 2

br’ 命令

構文:
br i1 <cond>, label <iftrue>, label <iffalse>
br label <dest>          ; Unconditional branch
概要:

br」命令は、現在の関数内の異なる基本ブロックに制御フローを転送するために使用されます。この命令には、条件付き分岐と無条件分岐に対応する2つの形式があります。

引数:

br」命令の条件付き分岐形式は、単一の「i1」値と2つの「label」値を受け取ります。「br」命令の無条件形式は、ターゲットとして単一の「label」値を受け取ります。

セマンティクス:

条件付き「br」命令を実行すると、「i1」引数が評価されます。値がtrueの場合、制御は「iftruelabel引数に流れます。「cond」がfalseの場合、制御は「iffalselabel引数に流れます。「cond」がpoisonまたはundefの場合、この命令は未定義の動作をします。

例:
Test:
  %cond = icmp eq i32 %a, %b
  br i1 %cond, label %IfEqual, label %IfUnequal
IfEqual:
  ret i32 1
IfUnequal:
  ret i32 0

switch’ 命令

構文:
switch <intty> <value>, label <defaultdest> [ <intty> <val>, label <dest> ... ]
概要:

switch」命令は、制御フローを複数の異なる場所に転送するために使用されます。これは「br」命令の一般化であり、多数の可能な宛先の1つに分岐できるようにします。

引数:

switch」命令は、3つのパラメータを使用します。整数比較値「value」、デフォルトの「label」宛先、および比較値定数と「label」のペアの配列です。テーブルに重複する定数エントリを含めることはできません。

セマンティクス:

switch命令は、値と宛先のテーブルを指定します。「switch」命令が実行されると、このテーブルが指定された値で検索されます。値が見つかった場合、制御フローは対応する宛先に転送されます。それ以外の場合、制御フローはデフォルトの宛先に転送されます。「value」がpoisonまたはundefの場合、この命令は未定義の動作をします。

実装:

ターゲットマシンのプロパティと特定のswitch命令に応じて、この命令はさまざまな方法でコード生成される可能性があります。たとえば、一連の連鎖された条件付き分岐として、またはルックアップテーブルを使用して生成される可能性があります。

例:
; Emulate a conditional br instruction
%Val = zext i1 %value to i32
switch i32 %Val, label %truedest [ i32 0, label %falsedest ]

; Emulate an unconditional br instruction
switch i32 0, label %dest [ ]

; Implement a jump table:
switch i32 %val, label %otherwise [ i32 0, label %onzero
                                    i32 1, label %onone
                                    i32 2, label %ontwo ]

indirectbr」命令

構文:
indirectbr ptr <address>, [ label <dest1>, label <dest2>, ... ]
概要:

indirectbr」命令は、現在の関数内のラベルへの間接分岐を実装します。そのアドレスは、「address」で指定されます。アドレスは、blockaddress定数から導出される必要があります。

引数:

address」引数は、ジャンプ先のラベルのアドレスです。残りの引数は、アドレスが指す可能性のある宛先の完全なセットを示します。ブロックは、宛先リストに複数回出現することが許可されていますが、これは特に役立つわけではありません。

この宛先リストは、データフロー分析でCFGを正確に理解するために必要です。

セマンティクス:

制御は、address引数で指定されたブロックに転送されます。可能性のあるすべての宛先ブロックはラベルリストにリストされている必要があります。そうしないと、この命令は未定義の動作をします。これは、他の関数で定義されたラベルへのジャンプも未定義の動作をすることを示唆しています。「address」がpoisonまたはundefの場合、この命令は未定義の動作をします。

実装:

これは通常、レジスタを介したジャンプで実装されます。

例:
indirectbr ptr %Addr, [ label %bb1, label %bb2, label %bb3 ]

invoke」命令

構文:
<result> = invoke [cconv] [ret attrs] [addrspace(<num>)] <ty>|<fnty> <fnptrval>(<function args>) [fn attrs]
              [operand bundles] to label <normal label> unwind label <exception label>
概要:

invoke」命令は、指定された関数への制御転送を引き起こし、制御フローが「normal」ラベルまたは「exception」ラベルのいずれかに転送される可能性があります。呼び出された関数が「ret」命令で戻った場合、制御フローは「normal」ラベルに戻ります。呼び出し先(または間接的な呼び出し先)が「resume」命令または他の例外処理メカニズムを介して戻った場合、制御は中断され、動的に最も近い「exception」ラベルで続行されます。

exception」ラベルは、例外のランディングパッドです。そのため、「exception」ラベルは、アンワインドが発生した後のプログラムの動作に関する情報を含む、「landingpad」命令を最初の非PHI命令として持つ必要があります。「landingpad」命令の制限により、「landingpad」命令に含まれる重要な情報が通常のコード移動によって失われないように、「invoke」命令に密接に結合されます。

引数:

この命令には、いくつかの引数が必要です。

  1. オプションの「cconv」マーカーは、呼び出しで使用する必要がある呼び出し規約を示します。指定されていない場合、呼び出しはデフォルトでC呼び出し規約を使用します。

  2. 戻り値のオプションのパラメータ属性リスト。ここでは、「zeroext」、「signext」、および「inreg」属性のみが有効です。

  3. オプションのaddrspace属性を使用して、呼び出される関数のアドレス空間を示すことができます。指定されていない場合、datalayout文字列のプログラムアドレス空間が使用されます。

  4. ty」:呼び出し命令自体の型であり、戻り値の型でもあります。値を返さない関数はvoidとしてマークされます。

  5. fnty」:呼び出される関数のシグネチャである必要があります。引数の型は、このシグネチャによって暗示される型と一致する必要があります。関数が可変個引数でない場合、この型は省略できます。

  6. fnptrval」:呼び出される関数へのポインタを含むLLVM値。ほとんどの場合、これは直接的な関数呼び出しですが、間接的なinvokeも同様に可能で、関数値への任意のポインタを呼び出します。

  7. function args」:関数シグネチャの引数型とパラメータ属性と一致する引数リスト。すべての引数は、first class型である必要があります。関数シグネチャが関数が可変個の引数を受け入れることを示している場合、追加の引数を指定できます。

  8. normal label」:呼び出された関数が「ret」命令を実行したときに到達するラベル。

  9. exception label」:呼び出し先がresume命令または他の例外処理メカニズムを介して戻ったときに到達するラベル。

  10. オプションの関数属性リスト。

  11. オプションのオペランドバンドルリスト。

セマンティクス:

この命令は、ほとんどの場合、標準の「call」命令として動作するように設計されています。主な違いは、ランタイムライブラリがスタックをアンワインドするために使用するラベルとの関連付けを確立することです。

この命令は、デストラクタを持つ言語で、longjmpまたはスローされた例外の場合に、適切なクリーンアップが実行されるようにするために使用されます。さらに、これは、それらをサポートする高レベル言語での「catch」句の実装にとっても重要です。

SSA形式の目的のために、「invoke」命令によって返される値の定義は、現在のブロックから「normal」ラベルへのエッジで発生すると見なされます。呼び出し先がアンワインドする場合、戻り値は使用できません。

例:
%retval = invoke i32 @Test(i32 15) to label %Continue
            unwind label %TestCleanup              ; i32:retval set
%retval = invoke coldcc i32 %Testfnptr(i32 15) to label %Continue
            unwind label %TestCleanup              ; i32:retval set

callbr」命令

構文:
<result> = callbr [cconv] [ret attrs] [addrspace(<num>)] <ty>|<fnty> <fnptrval>(<function args>) [fn attrs]
              [operand bundles] to label <fallthrough label> [indirect labels]
概要:

callbr」命令は、指定された関数への制御転送を引き起こし、制御フローが「fallthrough」ラベルまたは「indirect」ラベルのいずれかに転送される可能性があります。

この命令は、gccスタイルのインラインアセンブリの「goto」機能を実装するためにのみ使用する必要があります。他の使用法はすべて、IR検証のエラーです。

間接エッジに沿った出力をサポートするために、LLVMはクリティカルエッジを分割する必要がある場合があり、indirect labelsの代替ブロックを合成する必要がある場合があります。したがって、別のcallbr命令によって認識されるラベルのアドレス、またはblockaddress定数のアドレスは、この命令のindirect labelsオペランドに提供される同じブロックのアドレスと等しくない場合があります。アセンブリコードは、この命令のindirect labelsを介して提供されたアドレスにのみ制御を転送できます。

引数:

この命令には、いくつかの引数が必要です。

  1. オプションの「cconv」マーカーは、呼び出しで使用する必要がある呼び出し規約を示します。指定されていない場合、呼び出しはデフォルトでC呼び出し規約を使用します。

  2. 戻り値のオプションのパラメータ属性リスト。ここでは、「zeroext」、「signext」、および「inreg」属性のみが有効です。

  3. オプションのaddrspace属性を使用して、呼び出される関数のアドレス空間を示すことができます。指定されていない場合、datalayout文字列のプログラムアドレス空間が使用されます。

  4. ty」:呼び出し命令自体の型であり、戻り値の型でもあります。値を返さない関数はvoidとしてマークされます。

  5. fnty」:呼び出される関数のシグネチャである必要があります。引数の型は、このシグネチャによって暗示される型と一致する必要があります。関数が可変個引数でない場合、この型は省略できます。

  6. fnptrval’: 呼び出す関数へのポインターを含むLLVMの値。ほとんどの場合、これは直接的な関数呼び出しですが、他のcallbrも同様に可能で、任意の関数ポインター値を呼び出すことができます。

  7. function args」:関数シグネチャの引数型とパラメータ属性と一致する引数リスト。すべての引数は、first class型である必要があります。関数シグネチャが関数が可変個の引数を受け入れることを示している場合、追加の引数を指定できます。

  8. fallthrough label’: インラインアセンブリの実行が下端から終了したときに到達するラベル。

  9. indirect labels’: 呼び出し先が、‘fallthrough label’以外の場所に制御を移したときに到達するラベル。ラベル制約は、これらの宛先を参照します。

  10. オプションの関数属性リスト。

  11. オプションのオペランドバンドルリスト。

意味:

この命令は、ほとんどの場合、標準の‘call’命令として機能するように設計されています。主な違いは、呼び出し後の制御フローの行き先を定義するために、追加のラベルとの関連付けを確立することです。

callbr’命令の出力値は、‘fallthrough’ブロックと、任意の‘indirect’ブロックの両方で利用可能です。

この命令の今日の唯一の用途は、インラインアセンブリがジャンプする場所として追加のラベルを提供できるgccインラインアセンブリの「goto」機能を実装することです。

例:
; "asm goto" without output constraints.
callbr void asm "", "r,!i"(i32 %x)
            to label %fallthrough [label %indirect]

; "asm goto" with output constraints.
<result> = callbr i32 asm "", "=r,r,!i"(i32 %x)
            to label %fallthrough [label %indirect]

resume’ 命令

構文:
resume <type> <value>
概要:

resume’命令は、後続がないターミネータ命令です。

引数:

resume’命令は、同じ関数内の任意の‘landingpad’命令の結果と同じ型である必要のある1つの引数を必要とします。

意味:

resume’命令は、landingpad命令によって中断されたアンワインドが進行中の既存の(進行中の)例外の伝播を再開します。

例:
resume { ptr, i32 } %exn

catchswitch’ 命令

構文:
<resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind to caller
<resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind label <default>
概要:

catchswitch’命令は、LLVMの例外処理システムが、EHパーソナリティルーチンによって実行される可能性のあるキャッチハンドラーのセットを記述するために使用されます。

引数:

parent引数は、catchswitch命令を含むfuncletのトークンです。catchswitchがfunclet内ではない場合、このオペランドはトークンnoneである可能性があります。

default引数は、cleanuppadまたはcatchswitch命令のいずれかで始まる別の基本ブロックのラベルです。このアンワインドの宛先は、例外処理ドキュメントで説明されているように、parentリンクに関して有効なターゲットである必要があります。

handlersは、それぞれcatchpad命令で始まる、空ではない後続ブロックのリストです。

意味:

この命令を実行すると、handlersのいずれかの後続に制御が転送されるか、存在する場合はアンワインドラベルを介してアンワインドを継続します。

catchswitchは、ターミネータ命令であり、かつ「パッド」命令でもあります。つまり、基本ブロック内の最初の非phi命令であると同時に、最後の命令である必要があります。したがって、ブロック内の唯一の非phi命令である必要があります。

例:
dispatch1:
  %cs1 = catchswitch within none [label %handler0, label %handler1] unwind to caller
dispatch2:
  %cs2 = catchswitch within %parenthandler [label %handler0] unwind label %cleanup

catchret’ 命令

構文:
catchret from <token> to label <normal>
概要:

catchret’命令は、単一の後続を持つターミネータ命令です。

引数:

catchret’の最初の引数は、どのcatchpadを終了するかを示します。これはcatchpadである必要があります。‘catchret’の2番目の引数は、次に制御が転送される場所を指定します。

意味:

catchret’命令は、catchpad命令によって中断されたアンワインドが進行中の既存の(進行中の)例外を終了します。 パーソナリティ関数は、例えば、アクティブな例外を破棄するために任意のコードを実行する機会を得ます。その後、制御はnormalに転送されます。

token引数は、catchpad命令によって生成されたトークンである必要があります。指定されたcatchpadが、EHドキュメントで説明されているように、最も最近入力されたまだ終了していないfuncletパッドでない場合、catchretの動作は未定義です。

例:
catchret from %catch to label %continue

cleanupret’ 命令

構文:
cleanupret from <value> unwind label <continue>
cleanupret from <value> unwind to caller
概要:

cleanupret’命令は、オプションの後続を持つターミネータ命令です。

引数:

cleanupret’命令は、どのcleanuppadを終了するかを示す1つの引数を必要とし、cleanuppadである必要があります。指定されたcleanuppadが、EHドキュメントで説明されているように、最も最近入力されたまだ終了していないfuncletパッドでない場合、cleanupretの動作は未定義です。

cleanupret’命令には、オプションの後続であるcontinueもあります。これは、cleanuppadまたはcatchswitch命令のいずれかで始まる別の基本ブロックのラベルである必要があります。このアンワインドの宛先は、例外処理ドキュメントで説明されているように、parentリンクに関して有効なターゲットである必要があります。

意味:

cleanupret’命令は、制御を転送した1つのcleanuppadが終了したことをパーソナリティ関数に示します。制御をcontinueに転送するか、関数からアンワインドします。

例:
cleanupret from %cleanup unwind to caller
cleanupret from %cleanup unwind label %continue

unreachable’ 命令

構文:
unreachable
概要:

unreachable’命令には定義された意味はありません。この命令は、コードの特定の部分に到達できないことをオプティマイザに通知するために使用されます。これは、リターンしない関数の後のコードには到達できないことや、その他の事実を示すために使用できます。

意味:

unreachable’命令には定義された意味はありません。

単項演算

単項演算子は、単一のオペランドを必要とし、それに対して演算を実行し、単一の値を生成します。オペランドは、ベクターデータ型の場合のように、複数のデータを表す場合があります。結果の値は、オペランドと同じ型を持ちます。

fneg’命令

構文:
<result> = fneg [fast-math flags]* <ty> <op1>   ; yields ty:result
概要:

fneg’命令は、オペランドの否定を返します。

引数:

fneg’命令の引数は、浮動小数点または浮動小数点値のベクターでなければなりません。

意味:

生成される値は、符号ビットが反転されたオペランドのコピーです。値はそれ以外は完全に同一です。特に、入力がNaNの場合、quiet/signalingビットとペイロードは完全に保持されます。

この命令は、fast-mathフラグを任意個数受け取ることもできます。これは、安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = fneg float %val          ; yields float:result = -%var

二項演算

二項演算子は、プログラム内のほとんどの計算を行うために使用されます。それらは、同じ型の2つのオペランドを必要とし、それらに対して演算を実行し、単一の値を生成します。オペランドは、ベクターデータ型の場合のように、複数のデータを表す場合があります。結果の値は、オペランドと同じ型を持ちます。

いくつかの異なる二項演算子があります。

add’命令

構文:
<result> = add <ty> <op1>, <op2>          ; yields ty:result
<result> = add nuw <ty> <op1>, <op2>      ; yields ty:result
<result> = add nsw <ty> <op1>, <op2>      ; yields ty:result
<result> = add nuw nsw <ty> <op1>, <op2>  ; yields ty:result
概要:

add’命令は、2つのオペランドの和を返します。

引数:

add’命令の2つの引数は、整数または整数値のベクターでなければなりません。両方の引数は同じ型でなければなりません。

意味:

生成される値は、2つのオペランドの整数の和です。

和が符号なしオーバーフローした場合、返される結果は、結果のビット幅がnの場合、数学的な結果を2nで割った剰余になります。

LLVM整数は2の補数表現を使用するため、この命令は符号付き整数と符号なし整数の両方に適しています。

nuwnswは、それぞれ「No Unsigned Wrap(符号なしラップなし)」と「No Signed Wrap(符号付きラップなし)」を表します。nuwおよび/またはnswキーワードが存在する場合、addの結果値は、それぞれ符号なしおよび/または符号付きオーバーフローが発生した場合にpoison値となります。

例:
<result> = add i32 4, %var          ; yields i32:result = 4 + %var

fadd’命令

構文:
<result> = fadd [fast-math flags]* <ty> <op1>, <op2>   ; yields ty:result
概要:

fadd’命令は、2つのオペランドの和を返します。

引数:

fadd’命令の2つの引数は、浮動小数点または浮動小数点値のベクターでなければなりません。両方の引数は同じ型でなければなりません。

意味:

生成される値は、2つのオペランドの浮動小数点和です。この命令は、デフォルトの浮動小数点環境で実行されると想定されます。この命令は、fast-mathフラグを任意個数受け取ることもできます。これは、安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = fadd float 4.0, %var          ; yields float:result = 4.0 + %var

sub’命令

構文:
<result> = sub <ty> <op1>, <op2>          ; yields ty:result
<result> = sub nuw <ty> <op1>, <op2>      ; yields ty:result
<result> = sub nsw <ty> <op1>, <op2>      ; yields ty:result
<result> = sub nuw nsw <ty> <op1>, <op2>  ; yields ty:result
概要:

sub’命令は、2つのオペランドの差を返します。

sub’命令は、他のほとんどの中間表現に存在する‘neg’命令を表すために使用されることに注意してください。

引数:

sub’命令の2つの引数は、整数または整数値のベクターでなければなりません。両方の引数は同じ型でなければなりません。

意味:

生成される値は、2つのオペランドの整数差です。

差が符号なしオーバーフローした場合、返される結果は、結果のビット幅がnの場合、数学的な結果を2nで割った剰余になります。

LLVM整数は2の補数表現を使用するため、この命令は符号付き整数と符号なし整数の両方に適しています。

nuwnswは、それぞれ「No Unsigned Wrap(符号なしラップなし)」と「No Signed Wrap(符号付きラップなし)」を表します。nuwおよび/またはnswキーワードが存在する場合、subの結果値は、それぞれ符号なしおよび/または符号付きオーバーフローが発生した場合にpoison値となります。

例:
<result> = sub i32 4, %var          ; yields i32:result = 4 - %var
<result> = sub i32 0, %val          ; yields i32:result = -%var

fsub’命令

構文:
<result> = fsub [fast-math flags]* <ty> <op1>, <op2>   ; yields ty:result
概要:

fsub’命令は、2つのオペランドの差を返します。

引数:

fsub’命令の2つの引数は、浮動小数点または浮動小数点値のベクターでなければなりません。両方の引数は同じ型でなければなりません。

意味:

生成される値は、2つのオペランドの浮動小数点差です。この命令は、デフォルトの浮動小数点環境で実行されると想定されます。この命令は、fast-mathフラグを任意個数受け取ることもできます。これは、安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = fsub float 4.0, %var           ; yields float:result = 4.0 - %var
<result> = fsub float -0.0, %val          ; yields float:result = -%var

mul’命令

構文:
<result> = mul <ty> <op1>, <op2>          ; yields ty:result
<result> = mul nuw <ty> <op1>, <op2>      ; yields ty:result
<result> = mul nsw <ty> <op1>, <op2>      ; yields ty:result
<result> = mul nuw nsw <ty> <op1>, <op2>  ; yields ty:result
概要:

mul’命令は、2つのオペランドの積を返します。

引数:

mul’命令の2つの引数は、整数または整数値のベクターでなければなりません。両方の引数は同じ型でなければなりません。

意味:

生成される値は、2つのオペランドの整数積です。

乗算の結果が符号なしオーバーフローした場合、返される結果は、結果のビット幅がnの場合、数学的な結果を2nで割った剰余になります。

LLVMの整数は2の補数表現を使用しており、結果はオペランドと同じ幅になるため、この命令は符号付き整数と符号なし整数の両方に対して正しい結果を返します。完全な積(例えば、i32 * i32 -> i64)が必要な場合は、オペランドを完全な積の幅に合わせて、必要に応じて符号拡張またはゼロ拡張する必要があります。

nuwnswはそれぞれ「No Unsigned Wrap(符号なしラップなし)」と「No Signed Wrap(符号付きラップなし)」を表します。nuwまたはnswキーワードが存在する場合、符号なしオーバーフローまたは符号付きオーバーフローが発生すると、mulの結果値はpoison valueになります。

例:
<result> = mul i32 4, %var          ; yields i32:result = 4 * %var

fmul」命令

構文:
<result> = fmul [fast-math flags]* <ty> <op1>, <op2>   ; yields ty:result
概要:

fmul」命令は、2つのオペランドの積を返します。

引数:

fmul」命令の2つの引数は、浮動小数点または浮動小数点値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

生成される値は、2つのオペランドの浮動小数点積です。この命令は、デフォルトの浮動小数点環境で実行されると想定されます。この命令は、fast-math フラグをいくつでも取ることができます。これらは、そうでなければ安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = fmul float 4.0, %var          ; yields float:result = 4.0 * %var

udiv」命令

構文:
<result> = udiv <ty> <op1>, <op2>         ; yields ty:result
<result> = udiv exact <ty> <op1>, <op2>   ; yields ty:result
概要:

udiv」命令は、2つのオペランドの商を返します。

引数:

udiv」命令の2つの引数は、整数または整数値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

生成される値は、2つのオペランドの符号なし整数商です。

符号なし整数除算と符号付き整数除算は異なる演算であることに注意してください。符号付き整数除算には、「sdiv」を使用します。

ゼロによる除算は未定義の動作です。ベクターの場合、除数のいずれかの要素がゼロの場合、操作は未定義の動作になります。

exactキーワードが存在する場合、udivの結果値は、%op1が%op2の倍数でない場合(したがって、「((a udiv exact b) mul b) == a」)はpoison valueになります。

例:
<result> = udiv i32 4, %var          ; yields i32:result = 4 / %var

sdiv」命令

構文:
<result> = sdiv <ty> <op1>, <op2>         ; yields ty:result
<result> = sdiv exact <ty> <op1>, <op2>   ; yields ty:result
概要:

sdiv」命令は、2つのオペランドの商を返します。

引数:

sdiv」命令の2つの引数は、整数または整数値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

生成される値は、ゼロに向かって丸められた2つのオペランドの符号付き整数商です。

符号付き整数除算と符号なし整数除算は異なる演算であることに注意してください。符号なし整数除算には、「udiv」を使用します。

ゼロによる除算は未定義の動作です。ベクターの場合、除数のいずれかの要素がゼロの場合、操作は未定義の動作になります。オーバーフローも未定義の動作につながります。これはまれなケースですが、たとえば、-2147483648を-1で32ビット除算することで発生する可能性があります。

exactキーワードが存在する場合、sdivの結果値は、結果が丸められる場合はpoison valueになります。

例:
<result> = sdiv i32 4, %var          ; yields i32:result = 4 / %var

fdiv」命令

構文:
<result> = fdiv [fast-math flags]* <ty> <op1>, <op2>   ; yields ty:result
概要:

fdiv」命令は、2つのオペランドの商を返します。

引数:

fdiv」命令の2つの引数は、浮動小数点または浮動小数点値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

生成される値は、2つのオペランドの浮動小数点商です。この命令は、デフォルトの浮動小数点環境で実行されると想定されます。この命令は、fast-math フラグをいくつでも取ることができます。これらは、そうでなければ安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = fdiv float 4.0, %var          ; yields float:result = 4.0 / %var

urem」命令

構文:
<result> = urem <ty> <op1>, <op2>   ; yields ty:result
概要:

urem」命令は、2つの引数の符号なし除算からの剰余を返します。

引数:

urem」命令の2つの引数は、整数または整数値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

この命令は、除算の符号なし整数の *剰余* を返します。この命令は、剰余を取得するために常に符号なし除算を実行します。

符号なし整数剰余と符号付き整数剰余は異なる演算であることに注意してください。符号付き整数剰余には、「srem」を使用します。

ゼロによる除算の剰余を求めることは未定義の動作です。ベクターの場合、除数のいずれかの要素がゼロの場合、操作は未定義の動作になります。

例:
<result> = urem i32 4, %var          ; yields i32:result = 4 % %var

srem」命令

構文:
<result> = srem <ty> <op1>, <op2>   ; yields ty:result
概要:

srem」命令は、2つのオペランドの符号付き除算からの剰余を返します。この命令は、値のベクターバージョンも取ることができます。この場合、要素は整数である必要があります。

引数:

srem」命令の2つの引数は、整数または整数値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

この命令は、値の除算の *剰余* (結果はゼロであるか、被除数op1と同じ符号を持ちます)を返します。 *モジュロ* 演算子(結果はゼロであるか、除数op2と同じ符号を持ちます)ではありません。違いの詳細については、The Math Forumを参照してください。さまざまな言語でこれがどのように実装されているかの表については、Wikipedia:モジュロ演算を参照してください。

符号付き整数剰余と符号なし整数剰余は異なる演算であることに注意してください。符号なし整数剰余には、「urem」を使用します。

ゼロによる除算の剰余を求めることは未定義の動作です。ベクターの場合、除数のいずれかの要素がゼロの場合、操作は未定義の動作になります。オーバーフローも未定義の動作につながります。これはまれなケースですが、たとえば、-2147483648を-1で32ビット除算した剰余を取ることで発生する可能性があります。(剰余は実際にはオーバーフローしませんが、この規則により、sremは除算の結果と剰余の両方を返す命令を使用して実装できます。)

例:
<result> = srem i32 4, %var          ; yields i32:result = 4 % %var

frem」命令

構文:
<result> = frem [fast-math flags]* <ty> <op1>, <op2>   ; yields ty:result
概要:

frem」命令は、2つのオペランドの除算からの剰余を返します。

注記

この命令は、一部のターゲットではlibmの「fmod」への呼び出しとして実装され、命令を使用するにはlibmのリンクが必要になる場合があります。

引数:

frem」命令の2つの引数は、浮動小数点または浮動小数点値のベクターである必要があります。両方の引数は同じ型を持つ必要があります。

セマンティクス:

生成される値は、2つのオペランドの浮動小数点剰余です。これは、libm の ‘fmod’ 関数と同じ出力ですが、errno を設定する可能性はありません。剰余は被除数と同じ符号を持ちます。この命令は、デフォルトの 浮動小数点環境で実行されると想定されます。この命令は、任意の数の fast-math フラグも受け取ることができ、これは、通常は安全でない浮動小数点最適化を有効にするための最適化ヒントです。

例:
<result> = frem float 4.0, %var          ; yields float:result = 4.0 % %var

ビット単位の二項演算

ビット単位の二項演算子は、プログラム内でさまざまな形式のビット操作を行うために使用されます。これらは一般に非常に効率的な命令であり、他の命令からの強度削減によってよく実現できます。同じ型の2つのオペランドが必要で、それらに対して演算を実行し、単一の値を生成します。結果の値は、オペランドと同じ型です。

shl’ 命令

構文:
<result> = shl <ty> <op1>, <op2>           ; yields ty:result
<result> = shl nuw <ty> <op1>, <op2>       ; yields ty:result
<result> = shl nsw <ty> <op1>, <op2>       ; yields ty:result
<result> = shl nuw nsw <ty> <op1>, <op2>   ; yields ty:result
概要:

shl’ 命令は、最初のオペランドを指定されたビット数だけ左にシフトした値を返します。

引数:

shl’ 命令への両方の引数は、同じ 整数型または 整数ベクタ型である必要があります。 ‘op2’ は符号なしの値として扱われます。

セマンティクス:

生成される値は、op1 * 2op2 mod 2n です。ここで、n は結果の幅です。op2 が(静的または動的に)op1 のビット数以上の場合、この命令は poison 値を返します。引数がベクタの場合、op1 の各ベクタ要素は、op2 内の対応するシフト量だけシフトされます。

nuw キーワードが存在する場合、シフトによってゼロ以外のビットがシフトアウトされると、シフトは poison 値を生成します。 nsw キーワードが存在する場合、シフトによって結果の符号ビットと一致しないビットがシフトアウトされると、シフトは poison 値を生成します。

例:
<result> = shl i32 4, %var   ; yields i32: 4 << %var
<result> = shl i32 4, 2      ; yields i32: 16
<result> = shl i32 1, 10     ; yields i32: 1024
<result> = shl i32 1, 32     ; undefined
<result> = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 2, i32 4>

lshr’ 命令

構文:
<result> = lshr <ty> <op1>, <op2>         ; yields ty:result
<result> = lshr exact <ty> <op1>, <op2>   ; yields ty:result
概要:

lshr’ 命令(論理右シフト)は、最初のオペランドを指定されたビット数だけ右にシフトし、ゼロで埋めた値を返します。

引数:

lshr’ 命令への両方の引数は、同じ 整数型または 整数ベクタ型である必要があります。 ‘op2’ は符号なしの値として扱われます。

セマンティクス:

この命令は常に論理右シフト演算を実行します。結果の最上位ビットは、シフト後にゼロビットで埋められます。op2 が(静的または動的に)op1 のビット数以上の場合、この命令は poison 値を返します。引数がベクタの場合、op1 の各ベクタ要素は、op2 内の対応するシフト量だけシフトされます。

exact キーワードが存在する場合、シフトアウトされたビットがゼロ以外の場合、lshr の結果値は poison 値になります。

例:
<result> = lshr i32 4, 1   ; yields i32:result = 2
<result> = lshr i32 4, 2   ; yields i32:result = 1
<result> = lshr i8  4, 3   ; yields i8:result = 0
<result> = lshr i8 -2, 1   ; yields i8:result = 0x7F
<result> = lshr i32 1, 32  ; undefined
<result> = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1>

ashr’ 命令

構文:
<result> = ashr <ty> <op1>, <op2>         ; yields ty:result
<result> = ashr exact <ty> <op1>, <op2>   ; yields ty:result
概要:

ashr’ 命令(算術右シフト)は、最初のオペランドを指定されたビット数だけ右にシフトし、符号拡張した値を返します。

引数:

ashr’ 命令への両方の引数は、同じ 整数型または 整数ベクタ型である必要があります。 ‘op2’ は符号なしの値として扱われます。

セマンティクス:

この命令は常に算術右シフト演算を実行します。結果の最上位ビットは、op1 の符号ビットで埋められます。op2 が(静的または動的に)op1 のビット数以上の場合、この命令は poison 値を返します。引数がベクタの場合、op1 の各ベクタ要素は、op2 内の対応するシフト量だけシフトされます。

exact キーワードが存在する場合、シフトアウトされたビットがゼロ以外の場合、ashr の結果値は poison 値になります。

例:
<result> = ashr i32 4, 1   ; yields i32:result = 2
<result> = ashr i32 4, 2   ; yields i32:result = 1
<result> = ashr i8  4, 3   ; yields i8:result = 0
<result> = ashr i8 -2, 1   ; yields i8:result = -1
<result> = ashr i32 1, 32  ; undefined
<result> = ashr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 3>   ; yields: result=<2 x i32> < i32 -1, i32 0>

and’ 命令

構文:
<result> = and <ty> <op1>, <op2>   ; yields ty:result
概要:

and’ 命令は、2つのオペランドのビット単位論理積を返します。

引数:

and’ 命令への 2 つの引数は、整数型または 整数ベクタ型である必要があります。両方の引数は同じ型である必要があります。

セマンティクス:

and’ 命令に使用される真理値表は次のとおりです。

In0

In1

Out

0

0

0

0

1

0

1

0

0

1

1

1

例:
<result> = and i32 4, %var         ; yields i32:result = 4 & %var
<result> = and i32 15, 40          ; yields i32:result = 8
<result> = and i32 4, 8            ; yields i32:result = 0

or’ 命令

構文:
<result> = or <ty> <op1>, <op2>   ; yields ty:result
<result> = or disjoint <ty> <op1>, <op2>   ; yields ty:result
概要:

or’ 命令は、2つのオペランドのビット単位論理和を返します。

引数:

or’ 命令への 2 つの引数は、整数型または 整数ベクタ型である必要があります。両方の引数は同じ型である必要があります。

セマンティクス:

or’ 命令に使用される真理値表は次のとおりです。

In0

In1

Out

0

0

0

0

1

1

1

0

1

1

1

1

disjoint は、各ビットについて、そのビットが少なくとも1つの入力でゼロであることを意味します。これにより、どのビットからもキャリーが発生しないため、Or を Add として扱うことができます。disjoint キーワードが存在する場合、両方の入力が同じビット位置で 1 を持つ場合、or の結果値は poison 値になります。ベクタの場合、ビットを含む要素のみが poison になります。

例:
<result> = or i32 4, %var         ; yields i32:result = 4 | %var
<result> = or i32 15, 40          ; yields i32:result = 47
<result> = or i32 4, 8            ; yields i32:result = 12

xor’ 命令

構文:
<result> = xor <ty> <op1>, <op2>   ; yields ty:result
概要:

xor’ 命令は、2つのオペランドのビット単位の排他的論理和を返します。xor は、「1の補数」演算を実装するために使用されます。これは、Cの「~」演算子です。

引数:

xor’ 命令への 2 つの引数は、整数型または 整数ベクタ型である必要があります。両方の引数は同じ型である必要があります。

セマンティクス:

xor’ 命令に使用される真理値表は次のとおりです。

In0

In1

Out

0

0

0

0

1

1

1

0

1

1

1

0

例:
<result> = xor i32 4, %var         ; yields i32:result = 4 ^ %var
<result> = xor i32 15, 40          ; yields i32:result = 39
<result> = xor i32 4, 8            ; yields i32:result = 12
<result> = xor i32 %V, -1          ; yields i32:result = ~%V

ベクタ演算

LLVM は、ターゲットに依存しない方法でベクタ演算を表すためのいくつかの命令をサポートしています。これらの命令は、ベクタを効果的に処理するために必要な要素アクセスおよびベクタ固有の演算をカバーしています。LLVM はこれらのベクタ演算を直接サポートしていますが、多くの高度なアルゴリズムは、特定のターゲットを最大限に活用するためにターゲット固有の組み込み関数を使用することを望むでしょう。

extractelement’ 命令

構文:
<result> = extractelement <n x <ty>> <val>, <ty2> <idx>  ; yields <ty>
<result> = extractelement <vscale x n x <ty>> <val>, <ty2> <idx> ; yields <ty>
概要:

extractelement’ 命令は、指定されたインデックスにあるベクターから単一のスカラー要素を抽出します。

引数:

extractelement’ 命令の最初のオペランドは、ベクター型の値です。2番目のオペランドは、要素を抽出する位置を示すインデックスです。インデックスは任意の整数型の変数にすることができ、符号なし整数として扱われます。

セマンティクス:

結果は、val の要素型と同じ型のスカラーです。その値は、validx の位置にある値です。固定長のベクターの場合、idxval の長さを超えると、結果は poison 値になります。スケーラブルなベクターの場合、idx の値がベクターの実行時長を超える場合、結果は poison 値になります。

例:
<result> = extractelement <4 x i32> %vec, i32 0    ; yields i32

insertelement’ 命令

構文:
<result> = insertelement <n x <ty>> <val>, <ty> <elt>, <ty2> <idx>    ; yields <n x <ty>>
<result> = insertelement <vscale x n x <ty>> <val>, <ty> <elt>, <ty2> <idx> ; yields <vscale x n x <ty>>
概要:

insertelement’ 命令は、指定されたインデックスでスカラー要素をベクターに挿入します。

引数:

insertelement’ 命令の最初のオペランドは、ベクター型の値です。2番目のオペランドは、最初のオペランドの要素型と同じでなければならないスカラー値です。3番目のオペランドは、値を挿入する位置を示すインデックスです。インデックスは任意の整数型の変数にすることができ、符号なし整数として扱われます。

セマンティクス:

結果は、val と同じ型のベクターです。その要素の値は、idx の位置を除いて val の値と同じであり、その位置では値 elt を取得します。固定長のベクターの場合、idxval の長さを超えると、結果は poison 値になります。スケーラブルなベクターの場合、idx の値がベクターの実行時長を超える場合、結果は poison 値になります。

例:
<result> = insertelement <4 x i32> %vec, i32 1, i32 0    ; yields <4 x i32>

shufflevector’ 命令

構文:
<result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask>    ; yields <m x <ty>>
<result> = shufflevector <vscale x n x <ty>> <v1>, <vscale x n x <ty>> v2, <vscale x m x i32> <mask>  ; yields <vscale x m x <ty>>
概要:

shufflevector’ 命令は、2つの入力ベクターから要素の順列を構築し、入力と同じ要素型で、シャッフルマスクと同じ長さのベクターを返します。

引数:

shufflevector’ 命令の最初の2つのオペランドは、同じ型のベクターです。3番目の引数は、要素型が i32 であるシャッフルマスクのベクター定数です。マスクベクターの要素は、定数整数または poison 値でなければなりません。命令の結果は、長さがシャッフルマスクと同じで、要素型が最初の2つのオペランドの要素型と同じであるベクターです。

セマンティクス:

2つの入力ベクターの要素には、両方のベクターを横断して左から右に番号が付けられます。結果ベクターの各要素に対して、シャッフルマスクは、結果にコピーする入力ベクターのいずれかから要素を選択します。マスク内の非負の要素は、連結された入力ベクターのペアへのインデックスを表します。

マスクベクターの poison 要素は、結果の要素が poison であることを指定します。下位互換性の理由から、LLVM は一時的に undef マスク要素も受け入れますが、これは poison 要素と同じように解釈されます。シャッフルマスクが入力ベクターの1つから undef 要素を選択した場合、結果の要素は undef になります。

スケーラブルなベクターの場合、コンパイル時に長さが不明なベクターの場合、すべてのインデックスをリテラルとして記述できないため、現時点では有効なマスク値は zeroinitializerundef、および poison のみです。

例:
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
                        <4 x i32> <i32 0, i32 4, i32 1, i32 5>  ; yields <4 x i32>
<result> = shufflevector <4 x i32> %v1, <4 x i32> poison,
                        <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32> - Identity shuffle.
<result> = shufflevector <8 x i32> %v1, <8 x i32> poison,
                        <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32>
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
                        <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 >  ; yields <8 x i32>

集約操作

LLVM は、集約値を操作するためのいくつかの命令をサポートしています。

extractvalue’ 命令

構文:
<result> = extractvalue <aggregate type> <val>, <idx>{, <idx>}*
概要:

extractvalue’ 命令は、集約値からメンバーフィールドの値を抽出します。

引数:

extractvalue’ 命令の最初のオペランドは、構造体または 配列型の値です。他のオペランドは、‘getelementptr’ 命令のインデックスと同様の方法で、抽出する値を指定する定数インデックスです。

getelementptr インデックス作成との主な違いは、次のとおりです。

  • インデックス作成される値はポインターではないため、最初のインデックスは省略され、ゼロと見なされます。

  • 少なくとも1つのインデックスを指定する必要があります。

  • 構造体インデックスだけでなく、配列インデックスも境界内にある必要があります。

セマンティクス:

結果は、インデックスオペランドによって指定された集約内の位置にある値です。

例:
<result> = extractvalue {i32, float} %agg, 0    ; yields i32

insertvalue’ 命令

構文:
<result> = insertvalue <aggregate type> <val>, <ty> <elt>, <idx>{, <idx>}*    ; yields <aggregate type>
概要:

insertvalue’ 命令は、集約値のメンバーフィールドに値を挿入します。

引数:

insertvalue’ 命令の最初のオペランドは、構造体または 配列型の値です。2番目のオペランドは、挿入するファーストクラス値です。次のオペランドは、‘extractvalue’ 命令のインデックスと同様の方法で、値を挿入する位置を示す定数インデックスです。挿入する値は、インデックスで識別される値と同じ型である必要があります。

セマンティクス:

結果は、val と同じ型の集約です。その値は、インデックスで指定された位置の値が elt の値である点を除き、val の値です。

例:
%agg1 = insertvalue {i32, float} undef, i32 1, 0              ; yields {i32 1, float undef}
%agg2 = insertvalue {i32, float} %agg1, float %val, 1         ; yields {i32 1, float %val}
%agg3 = insertvalue {i32, {float}} undef, float %val, 1, 0    ; yields {i32 undef, {float %val}}

メモリアクセスとアドレス指定操作

SSA ベースの表現の重要な設計ポイントは、メモリをどのように表現するかです。LLVM では、メモリロケーションは SSA 形式になっていないため、非常に簡単になります。このセクションでは、LLVM でのメモリの読み取り、書き込み、および割り当ての方法について説明します。

alloca’ 命令

構文:
<result> = alloca [inalloca] <type> [, <ty> <NumElements>] [, align <alignment>] [, addrspace(<num>)]     ; yields type addrspace(num)*:result
概要:

alloca’ 命令は、現在実行中の関数のスタックフレームにメモリを割り当て、この関数が呼び出し元に戻るときに自動的に解放されるようにします。アドレス空間が明示的に指定されていない場合、オブジェクトは datalayout 文字列から alloca アドレス空間に割り当てられます。

引数:

alloca’ 命令は、ランタイムスタック上に sizeof(<type>)*NumElements バイトのメモリを割り当て、プログラムに対して適切な型のポインタを返します。「NumElements」が指定されている場合は、割り当てられる要素の数であり、そうでない場合は「NumElements」はデフォルトで1になります。

定数のアライメントが指定されている場合、割り当ての結果の値は少なくともその境界にアラインされることが保証されます。アライメントは 1 << 32 より大きくすることはできません。

アライメントはテキストIRの解析時のみオプションであり、メモリ内IRでは常に存在します。指定されていない場合、ターゲットは型と互換性のある都合の良い境界に割り当てをアラインすることを選択できます。

type’ は任意のサイズの型を使用できます。

スケーラブルベクターを含む構造体は、すべてのフィールドが同じスケーラブルベクター型である場合を除き、allocaで使用できません(例:{<vscale x 2 x i32>, <vscale x 2 x i32>} は同じ型を含みますが、{<vscale x 2 x i32>, <vscale x 2 x i64>} はそうではありません)。

セマンティクス:

メモリが割り当てられ、ポインタが返されます。割り当てられたメモリは初期化されておらず、初期化されていないメモリからの読み込みは未定義の値を生成します。割り当てのための十分なスタックスペースがない場合、操作自体が未定義になります。‘alloca’ で割り当てられたメモリは、関数が返るときに自動的に解放されます。 ‘alloca’ 命令は、アドレスが利用可能である必要がある自動変数を表すためによく使用されます。関数が(ret 命令または resume 命令のいずれかで)返るとき、メモリは再利用されます。ゼロバイトの割り当ては合法ですが、返されるポインタは一意ではない可能性があります。メモリが割り当てられる順序(つまり、スタックが拡張される方向)は指定されていません。

datalayout 文字列の alloca アドレス空間外の ‘alloca’ は、ターゲットがセマンティクスを割り当てている場合にのみ意味があることに注意してください。

返されたポインタが llvm.lifetime.start によって使用される場合、返されたオブジェクトは最初はデッドです。ライフサイクルを操作する組み込み関数の正確なセマンティクスについては、llvm.lifetime.start および llvm.lifetime.end を参照してください。

例:
%ptr = alloca i32                             ; yields ptr
%ptr = alloca i32, i32 4                      ; yields ptr
%ptr = alloca i32, i32 4, align 1024          ; yields ptr
%ptr = alloca i32, align 1024                 ; yields ptr

load’ 命令

構文:
<result> = load [volatile] <ty>, ptr <pointer>[, align <alignment>][, !nontemporal !<nontemp_node>][, !invariant.load !<empty_node>][, !invariant.group !<empty_node>][, !nonnull !<empty_node>][, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>][, !align !<align_node>][, !noundef !<empty_node>]
<result> = load atomic [volatile] <ty>, ptr <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<empty_node>]
!<nontemp_node> = !{ i32 1 }
!<empty_node> = !{}
!<deref_bytes_node> = !{ i64 <dereferenceable_bytes> }
!<align_node> = !{ i64 <value_alignment> }
概要:

load’ 命令は、メモリから読み取るために使用されます。

引数:

load 命令への引数は、ロード元のメモリアドレスを指定します。指定された型は、既知のサイズの ファーストクラス 型(つまり、不透明な構造型 を含まない型)である必要があります。loadvolatile とマークされている場合、オプティマイザーは、この load の実行数や他の volatile 操作 との実行順序を変更することは許可されません。

loadatomic とマークされている場合、追加の 順序付け とオプションの syncscope("<target-scope>") 引数を受け取ります。release および acq_rel の順序付けは、load 命令では有効ではありません。アトミックロードは、複数のアトミックストアを参照する可能性がある場合に 定義済み の結果を生成します。ポインタが指す先の型は、ビット幅が 8 以上でターゲット固有のサイズ制限以下の 2 のべき乗である整数、ポインタ、または浮動小数点型である必要があります。align は、アトミックロードで明示的に指定する必要があります。注:アライメントが <value> 型のサイズ以上でない場合、アトミック操作はロックを必要とし、パフォーマンスが低下する可能性があります。!nontemporal は、アトミックロードに対して定義されたセマンティクスを持ちません。

オプションの定数 align 引数は、操作のアライメント(つまり、メモリアドレスのアライメント)を指定します。アライメント情報が正しいことを保証するのはコードエミッターの責任です。アライメントを過大評価すると、未定義の動作になります。アライメントを過小評価すると、コードの効率が低下する可能性があります。アライメント 1 は常に安全です。可能な最大のアライメントは 1 << 32 です。ロードされた型のサイズよりも高いアライメント値は、アライメント値のバイト数までのメモリを、デフォルトのアドレス空間でトラップすることなく安全にロードできることを意味します。上位バイトへのアクセスはデバッグツールに干渉する可能性があるため、関数に sanitize_thread または sanitize_address 属性がある場合はアクセスしないでください。

アライメントはテキストIRの解析時のみオプションであり、メモリ内IRでは常に存在します。省略された align 引数は、操作がターゲットの ABI アライメントを持つことを意味します。

オプションの !nontemporal メタデータは、値が 1 の i32 エントリを 1 つ持つメタデータノードに対応する単一のメタデータ名 <nontemp_node> を参照する必要があります。命令の !nontemporal メタデータの存在は、このロードがキャッシュで再利用されるとは予想されないことをオプティマイザーとコードジェネレーターに伝えます。コードジェネレーターは、x86 の MOVNT 命令など、キャッシュ帯域幅を節約するための特別な命令を選択できます。

オプションの !invariant.load メタデータは、エントリがないメタデータノードに対応する単一のメタデータ名 <empty_node> を参照する必要があります。!invariant.load メタデータでタグ付けされたロード命令が実行される場合、ロードによって参照されるメモリ位置には、そのメモリ位置が逆参照可能であるプログラム内のすべてのポイントで同じ値が含まれている必要があります。そうでない場合、動作は未定義です。

オプションの !invariant.group メタデータは、単一のメタデータ名を参照する必要があります

<empty_node> (エントリがないメタデータノードに対応)。 invariant.group メタデータ invariant.group を参照してください。

オプションの !nonnull メタデータは、エントリがないメタデータノードに対応する単一のメタデータ名 <empty_node> を参照する必要があります。命令の !nonnull メタデータの存在は、ロードされた値が null にならないことがわかっていることをオプティマイザーに伝えます。ランタイム時に値が null の場合、代わりにポイズン値が返されます。これは、パラメータと戻り値の nonnull 属性に類似しています。このメタデータは、ポインタ型のロードにのみ適用できます。

オプションの !dereferenceable メタデータは、1 つの i64 エントリを持つメタデータノードに対応する単一のメタデータ名 <deref_bytes_node> を参照する必要があります。 dereferenceable メタデータ dereferenceable を参照してください。

オプションの !dereferenceable_or_null メタデータは、1 つの i64 エントリを持つメタデータノードに対応する単一のメタデータ名 <deref_bytes_node> を参照する必要があります。 dereferenceable_or_null メタデータ dereferenceable_or_null を参照してください。

オプションの !align メタデータは、1 つの i64 エントリを持つメタデータノードに対応する単一のメタデータ名 <align_node> を参照する必要があります。命令の !align メタデータの存在は、ロードされた値がメタデータノードの整数値によって指定された境界にアラインされることがわかっていることをオプティマイザーに伝えます。アライメントは 2 のべき乗である必要があります。これは、パラメータと戻り値の「アライン」属性に類似しています。このメタデータは、ポインタ型のロードにのみ適用できます。返された値がランタイム時に適切にアラインされていない場合、代わりにポイズン値が返されます。

オプションの !noundef メタデータは、エントリのないノードに対応する単一のメタデータ名 <empty_node> を参照する必要があります。命令に !noundef メタデータが存在する場合、読み込まれた値が適切に定義されている ことをオプティマイザーに伝えます。値が適切に定義されていない場合、動作は未定義です。!noundef メタデータが !nonnull のような poison を生成するメタデータと組み合わされた場合、そのメタデータ制約に違反すると、未定義の動作になります。

セマンティクス:

指定されたメモリ位置からメモリがロードされます。ロードされる値がスカラー型の場合、読み取られるバイト数は、その型のすべてのビットを保持するために必要な最小バイト数を超えません。たとえば、i24 をロードすると、最大3バイトが読み取られます。バイト数の整数倍でないサイズを持つ i20 のような型の値をロードする場合、その値が元々同じ型のストアを使用して書き込まれていなかった場合、結果は未定義になります。ロードされる値が集約型の場合、パディングに対応するバイトにはアクセスできますが、無視されます。これは、ロードされた集約値からパディングを観測することが不可能であるためです。<pointer> が適切に定義された値でない場合、動作は未定義です。

例:
%ptr = alloca i32                               ; yields ptr
store i32 3, ptr %ptr                           ; yields void
%val = load i32, ptr %ptr                       ; yields i32:val = i32 3

store’ 命令

構文:
store [volatile] <ty> <value>, ptr <pointer>[, align <alignment>][, !nontemporal !<nontemp_node>][, !invariant.group !<empty_node>]        ; yields void
store atomic [volatile] <ty> <value>, ptr <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<empty_node>] ; yields void
!<nontemp_node> = !{ i32 1 }
!<empty_node> = !{}
概要:

store’ 命令は、メモリへの書き込みに使用されます。

引数:

store 命令には、ストアする値と、それをストアするアドレスの2つの引数があります。<pointer> オペランドの型は、<value> オペランドのファーストクラス型へのポインターである必要があります。storevolatile としてマークされている場合、オプティマイザーは、この store の実行回数または他の揮発性操作との実行順序を変更することはできません。ファーストクラス型の既知のサイズ(つまり、不透明な構造型を含まない)の値のみがストアできます。

storeatomic としてマークされている場合、追加の順序付けとオプションの syncscope("<target-scope>") 引数を取ります。acquire および acq_rel の順序付けは、store 命令では無効です。アトミックロードは、複数のアトミックストアを参照する可能性がある場合に定義された結果を生成します。ポインティの型は、ビット幅が8以上の2のべき乗で、ターゲット固有のサイズ制限以下の整数型、ポインター型、または浮動小数点型である必要があります。align は、アトミックストアで明示的に指定する必要があります。注:アライメントが <value> 型のサイズ以上でない場合、アトミック操作はロックを必要とし、パフォーマンスが低下する可能性があります。!nontemporal は、アトミックストアに対して定義されたセマンティクスを持ちません。

オプションの定数 align 引数は、操作のアライメント(つまり、メモリアドレスのアライメント)を指定します。アライメント情報が正しいことを保証するのはコードエミッターの責任です。アライメントを過大評価すると、未定義の動作になります。アライメントを過小評価すると、コードの効率が低下する可能性があります。アライメント 1 は常に安全です。可能な最大のアライメントは 1 << 32 です。ロードされた型のサイズよりも高いアライメント値は、アライメント値のバイト数までのメモリを、デフォルトのアドレス空間でトラップすることなく安全にロードできることを意味します。上位バイトへのアクセスはデバッグツールに干渉する可能性があるため、関数に sanitize_thread または sanitize_address 属性がある場合はアクセスしないでください。

アライメントはテキストIRの解析時のみオプションであり、メモリ内IRでは常に存在します。省略された align 引数は、操作がターゲットの ABI アライメントを持つことを意味します。

オプションの !nontemporal メタデータは、値が 1 の i32 エントリを 1 つ持つメタデータノードに対応する単一のメタデータ名 <nontemp_node> を参照する必要があります。命令の !nontemporal メタデータの存在は、このロードがキャッシュで再利用されるとは予想されないことをオプティマイザーとコードジェネレーターに伝えます。コードジェネレーターは、x86 の MOVNT 命令など、キャッシュ帯域幅を節約するための特別な命令を選択できます。

オプションの !invariant.group メタデータは、単一のメタデータ名 <empty_node> を参照する必要があります。invariant.group メタデータを参照してください。

セマンティクス:

メモリの内容は、<pointer> オペランドで指定された場所で <value> を含むように更新されます。<value> がスカラー型の場合、書き込まれるバイト数は、その型のすべてのビットを保持するために必要な最小バイト数を超えません。たとえば、i24 をストアすると、最大3バイトが書き込まれます。バイト数の整数倍でないサイズを持つ i20 のような型の値を書き込む場合、その型に属さない余分なビットがどうなるかは不明ですが、通常は上書きされます。<value> が集約型の場合、パディングはundefで埋められます。<pointer> が適切に定義された値でない場合、動作は未定義です。

例:
%ptr = alloca i32                               ; yields ptr
store i32 3, ptr %ptr                           ; yields void
%val = load i32, ptr %ptr                       ; yields i32:val = i32 3

fence’ 命令

構文:
fence [syncscope("<target-scope>")] <ordering>  ; yields void
概要:

fence’ 命令は、操作間に happens-before エッジを導入するために使用されます。

引数:

fence’ 命令は、それらが追加する _synchronizes-with_ エッジを定義する順序付け引数を取ります。それらは acquirereleaseacq_rel、および seq_cst の順序付けのみが与えられます。

セマンティクス:

(少なくとも)release 順序付けセマンティクスを持つフェンス A は、原子オブジェクト M で操作するアトミック操作 X および Y が存在し、A が X の前に順序付けされ、X が M を変更し(直接または X が先頭に立つシーケンスの副作用を介して)、Y が B の前に順序付けされ、Y が M を観測する場合にのみ、(少なくとも)acquire 順序付けセマンティクスを持つフェンス B と _synchronizes with_ します。これにより、A と B の間に _happens-before_ 依存関係が提供されます。明示的な fence ではなく、アトミック操作 X または Y の一方(両方ではない)が release または acquire(resp.)順序制約を提供し、明示的な fence と _synchronize-with_ し、_happens-before_ エッジを確立することができます。

seq_cst 順序付けを持つ fence は、上記の acquirerelease の両方のセマンティクスに加えて、他の seq_cst 操作および/またはフェンスのグローバルプログラム順序に参加します。さらに、seq_cst フェンスによって作成されたグローバル順序は、そのようなフェンスの前後に発生する monotonic (またはより強力な)メモリアクセスの個々の総順序と互換性がある必要があります。この相互作用の正確なセマンティクスはやや複雑です。詳細については、C++ 標準の[atomics.order] セクションを参照してください。

fence 命令は、オプションの “syncscope” 引数も取ることができます。

例:
fence acquire                                        ; yields void
fence syncscope("singlethread") seq_cst              ; yields void
fence syncscope("agent") seq_cst                     ; yields void

cmpxchg’ 命令

構文:
cmpxchg [weak] [volatile] ptr <pointer>, <ty> <cmp>, <ty> <new> [syncscope("<target-scope>")] <success ordering> <failure ordering>[, align <alignment>] ; yields  { ty, i1 }
概要:

cmpxchg’ 命令は、メモリをアトミックに修正するために使用されます。メモリ内の値をロードし、それを指定された値と比較します。それらが等しい場合、新しい値をメモリにストアしようとします。

引数:

cmpxchg’ 命令には、操作するアドレス、現在そのアドレスにある値と比較する値、比較した値が等しい場合にそのアドレスに配置する新しい値の3つの引数があります。 ‘<cmp>’ の型は、ビット幅が8以上の2のべき乗で、ターゲット固有のサイズ制限以下の整数型またはポインター型である必要があります。 ‘<cmp>’ と ‘<new>’ は同じ型である必要があり、 ‘<pointer>’ の型はその型へのポインターである必要があります。cmpxchgvolatile としてマークされている場合、オプティマイザーは、他の揮発性操作を使用したこの cmpxchg の実行回数または順序を変更することはできません。

成功と失敗の順序付け引数は、この cmpxchg が他のアトミック操作とどのように同期するかを指定します。両方の順序付けパラメーターは、少なくとも monotonic である必要があり、失敗の順序付けは release または acq_rel のいずれかであってはなりません。

cmpxchg 命令は、オプションの “syncscope” 引数も取ることができます。

注:アライメントが <value> 型のサイズ以上でない場合、アトミック操作はロックを必要とし、パフォーマンスが低下する可能性があります。

アライメントは、テキスト IR を解析する場合にのみオプションです。メモリ内 IR の場合、常に存在します。指定しない場合、アライメントは ‘<value>’ 型のサイズと同じであると想定されます。このデフォルトのアライメントの仮定は、アライメントが指定されていない場合に load/store 命令に使用されるアライメントとは異なることに注意してください。

cmpxchg に渡されるポインターは、オペランドのメモリ内のサイズ以上の配置を持っている必要があります。

セマンティクス:

<pointer> オペランドで指定されたメモリ位置の内容が読み込まれ、<cmp> と比較されます。値が等しい場合、<new> がその位置に書き込まれます。元の値と、成功 (true) または失敗 (false) を示すフラグが返されます。

cmpxchg 操作が weak としてマークされている場合、偽の失敗が許可されます。比較が一致した場合でも、操作で <new> が書き込まれない可能性があります。

cmpxchg 操作が strong (デフォルト) の場合、読み込まれた値が cmp と等しい場合に限り、i1 値は 1 になります。

成功した cmpxchg は、リリースシーケンスを識別するためのリード・モディファイ・ライト命令です。失敗した cmpxchg は、2 番目の順序付けパラメータによって決定される順序付けパラメータを持つアトミックロードと同等です。

例:
entry:
  %orig = load atomic i32, ptr %ptr unordered, align 4                      ; yields i32
  br label %loop

loop:
  %cmp = phi i32 [ %orig, %entry ], [%value_loaded, %loop]
  %squared = mul i32 %cmp, %cmp
  %val_success = cmpxchg ptr %ptr, i32 %cmp, i32 %squared acq_rel monotonic ; yields  { i32, i1 }
  %value_loaded = extractvalue { i32, i1 } %val_success, 0
  %success = extractvalue { i32, i1 } %val_success, 1
  br i1 %success, label %done, label %loop

done:
  ...

atomicrmw」命令

構文:
atomicrmw [volatile] <operation> ptr <pointer>, <ty> <value> [syncscope("<target-scope>")] <ordering>[, align <alignment>]  ; yields ty
概要:

atomicrmw」命令は、メモリをアトミックに変更するために使用されます。

引数:

atomicrmw」命令には、適用する操作、変更する値のアドレス、操作の引数の 3 つの引数があります。操作は、次のキーワードのいずれかである必要があります。

  • xchg

  • add

  • sub

  • and

  • nand

  • or

  • xor

  • max

  • min

  • umax

  • umin

  • fadd

  • fsub

  • fmax

  • fmin

  • uinc_wrap

  • udec_wrap

これらのほとんどの操作では、<value> の型は、ビット幅が 8 以上で、ターゲット固有のサイズ制限以下の 2 の累乗である整数型である必要があります。xchg の場合、これは浮動小数点型または整数と同じサイズ制約を持つポインター型である場合もあります。fadd/fsub/fmax/fmin の場合、これは浮動小数点型または浮動小数点型の固定ベクトルである必要があります。<pointer> オペランドの型は、その型へのポインターである必要があります。atomicrmwvolatile としてマークされている場合、オプティマイザーは、この atomicrmw と他の volatile 操作 の実行の数や順序を変更することは許可されていません。

注:アライメントが <value> 型のサイズ以上でない場合、アトミック操作はロックを必要とし、パフォーマンスが低下する可能性があります。

アライメントは、テキスト IR を解析する場合にのみオプションです。メモリ内 IR の場合、常に存在します。指定しない場合、アライメントは ‘<value>’ 型のサイズと同じであると想定されます。このデフォルトのアライメントの仮定は、アライメントが指定されていない場合に load/store 命令に使用されるアライメントとは異なることに注意してください。

atomicrmw 命令は、オプションの「syncscope」引数も取ることができます。

セマンティクス:

<pointer> オペランドで指定されたメモリ位置の内容がアトミックに読み取られ、変更され、書き戻されます。その位置の元の値が返されます。変更は、操作引数によって指定されます。

  • xchg: *ptr = val

  • add: *ptr = *ptr + val

  • sub: *ptr = *ptr - val

  • and: *ptr = *ptr & val

  • nand: *ptr = ~(*ptr & val)

  • or: *ptr = *ptr | val

  • xor: *ptr = *ptr ^ val

  • max: *ptr = *ptr > val ? *ptr : val (符号付き比較を使用)

  • min: *ptr = *ptr < val ? *ptr : val (符号付き比較を使用)

  • umax: *ptr = *ptr > val ? *ptr : val (符号なし比較を使用)

  • umin: *ptr = *ptr < val ? *ptr : val (符号なし比較を使用)

  • fadd: *ptr = *ptr + val (浮動小数点演算を使用)

  • fsub: *ptr = *ptr - val (浮動小数点演算を使用)

  • fmax: *ptr = maxnum(*ptr, val) (llvm.maxnum.* 組み込み関数に一致)

  • fmin: *ptr = minnum(*ptr, val) (llvm.minnum.* 組み込み関数に一致)

  • uinc_wrap: *ptr = (*ptr u>= val) ? 0 : (*ptr + 1) (入力値を超えてインクリメントされた場合にゼロに折り返す値のインクリメント)

  • udec_wrap: *ptr = ((*ptr == 0) || (*ptr u> val)) ? val : (*ptr - 1) (ゼロを下回ってデクリメントされた場合に入力値に折り返すデクリメント)。

例:
%old = atomicrmw add ptr %ptr, i32 1 acquire                        ; yields i32

getelementptr」命令

構文:
<result> = getelementptr <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr inbounds <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr nusw <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr nuw <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr inrange(S,E) <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr <ty>, <N x ptr> <ptrval>, <vector index type> <idx>
概要:

getelementptr」命令は、aggregate データ構造のサブ要素のアドレスを取得するために使用されます。アドレス計算のみを実行し、メモリにはアクセスしません。この命令は、そのようなアドレスのベクトルを計算するためにも使用できます。

引数:

最初の引数は常に、計算の基礎として使用される型です。2 番目の引数は常に、ポインターまたはポインターのベクトルであり、開始するベースアドレスです。残りの引数は、集約オブジェクトのどの要素がインデックス付けされるかを示すインデックスです。各インデックスの解釈は、インデックス付けされる型によって異なります。最初のインデックスは常に、2 番目の引数として与えられたポインター値をインデックス付けします。2 番目のインデックスは、指される型の値をインデックス付けします (最初のインデックスがゼロ以外の場合、直接指される値とは限りません)。最初のインデックス付けされる型はポインター値である必要があり、後続の型は配列、ベクトル、および構造体である可能性があります。後続のインデックス付けされる型は、計算を続行する前にポインターをロードする必要があるため、ポインターになることは決してないことに注意してください。

各インデックス引数の型は、インデックス付けされる型によって異なります。(オプションでパックされた) 構造体をインデックス付けする場合、i32 整数の定数のみが許可されます (インデックスのベクトルを使用する場合、それらはすべて同じ i32 整数の定数である必要があります)。配列、ポインター、またはベクトルをインデックス付けする場合、任意の幅の整数が許可され、定数である必要はありません。これらの整数は、関連する場所で符号付き値として扱われます。

たとえば、C コードの断片と、それが LLVM にどのようにコンパイルされるかを考えてみましょう。

struct RT {
  char A;
  int B[10][20];
  char C;
};
struct ST {
  int X;
  double Y;
  struct RT Z;
};

int *foo(struct ST *s) {
  return &s[1].Z.B[5][13];
}

Clang によって生成された LLVM コードはほぼ次のようになります。

%struct.RT = type { i8, [10 x [20 x i32]], i8 }
%struct.ST = type { i32, double, %struct.RT }

define ptr @foo(ptr %s) {
entry:
  %arrayidx = getelementptr inbounds %struct.ST, ptr %s, i64 1, i32 2, i32 1, i64 5, i64 13
  ret ptr %arrayidx
}
セマンティクス:

上記の例では、最初のインデックスはポインターである「%struct.ST*」型をインデックス付けしており、「%struct.ST」 = 「{ i32, double, %struct.RT }」型、つまり構造体を生成します。2 番目のインデックスは、構造体の 3 番目の要素をインデックス付けしており、「%struct.RT」 = 「{ i8 , [10 x [20 x i32]], i8 }」型、つまり別の構造体を生成します。3 番目のインデックスは、構造体の 2 番目の要素をインデックス付けしており、「[10 x [20 x i32]]」型、つまり配列を生成します。配列の 2 つの次元がサブスクリプト化され、「i32」型を生成します。「getelementptr」命令は、この要素へのポインターを返します。

構造体を部分的にインデックス付けして、内部要素へのポインターを返すことは完全に合法であることに注意してください。このため、与えられたテストケースの LLVM コードは次と同等です。

define ptr @foo(ptr %s) {
  %t1 = getelementptr %struct.ST, ptr %s, i32 1
  %t2 = getelementptr %struct.ST, ptr %t1, i32 0, i32 2
  %t3 = getelementptr %struct.RT, ptr %t2, i32 0, i32 1
  %t4 = getelementptr [10 x [20 x i32]], ptr %t3, i32 0, i32 5
  %t5 = getelementptr [20 x i32], ptr %t4, i32 0, i32 13
  ret ptr %t5
}

まず、インデックスはポインターのインデックス型におけるオフセットに変換されます。現在インデックスされている型が構造体型である場合、インデックスに対応する構造体のオフセットは、ポインターのインデックス型に合わせて符号拡張または切り捨てられます。そうでない場合、インデックス自体が符号拡張または切り捨てられ、その後、現在インデックスされている型の型アロケーションサイズ(つまり、ABIアラインメントに合わせて切り上げられたサイズ)が掛けられます。

次に、オフセットは、ベースアドレスの下位ビットに、インデックス型の幅まで、暗黙的にラップする2の補数演算で加算されます。ポインターサイズがインデックスサイズよりも大きい場合、これはインデックス型の幅を超えるビットが影響を受けないことを意味します。

getelementptrの結果値は、ベースポインターが指すオブジェクトの範囲外である可能性があります。結果値は、割り当てられたストレージを指している場合でも、必ずしもメモリへのアクセスに使用されるとは限りません。詳細については、ポインターエイリアシング規則のセクションを参照してください。

getelementptr命令には、追加の規則を課す属性がいくつかある場合があります。いずれかの規則に違反した場合、結果値はpoison値になります。ベースがポインターのベクターである場合、属性は各計算要素ごとに適用されます。

nusw(符号なしの符号付きラップなし)の場合

  • インデックスの型がポインターインデックス型よりも大きい場合、ポインターインデックス型への切り捨ては符号付きの値を保持します(trunc nsw)。

  • インデックスに型サイズを掛ける演算は、符号付きの意味でポインターインデックス型をラップしません(mul nsw)。

  • 各オフセットの連続した加算(ベースアドレスの加算を除く)は、符号付きの意味でポインターインデックス型をラップしません(add nsw)。

  • ポインターインデックス型に切り捨てられ、符号なしの数値として解釈された現在のアドレスと、符号付きの数値として解釈された各オフセットの連続した加算は、ポインターインデックス型をラップしません。

nuw(符号なしラップなし)の場合

  • インデックスの型がポインターインデックス型よりも大きい場合、ポインターインデックス型への切り捨ては符号なしの値を保持します(trunc nuw)。

  • インデックスに型サイズを掛ける演算は、符号なしの意味でポインターインデックス型をラップしません(mul nuw)。

  • 各オフセットの連続した加算(ベースアドレスの加算を除く)は、符号なしの意味でポインターインデックス型をラップしません(add nuw)。

  • ポインターインデックス型に切り捨てられ、符号なしの数値として解釈された現在のアドレスと、同じく符号なしの数値として解釈された各オフセットの連続した加算は、ポインターインデックス型をラップしません(add nuw)。

inboundsの場合、nusw属性のすべての規則が適用されます。さらに、getelementptrにゼロ以外のインデックスがある場合、次の規則が適用されます。

  • ベースポインターには、それがベースとしている割り当てられたオブジェクトのインバウンドアドレスがあります。これは、それがその割り当てられたオブジェクトの中またはその終端を指していることを意味します。オブジェクトはもはやライブである必要はないことに注意してください。割り当て解除されたオブジェクトのインバウンドであることは十分です。

  • アドレスへのオフセットの連続した加算の間、結果のポインターは各ステップで割り当てられたオブジェクトのインバウンドのままでなければなりません。

すべてゼロのインデックスを持つgetelementptrは、ベースポインターが割り当てられたオブジェクトを指していない場合でも、常にinboundsと見なされることに注意してください。当然の結果として、デフォルトのアドレス空間におけるnullポインターのインバウンドである唯一のポインターは、nullポインター自体です。

これらの規則は、割り当てられたオブジェクトが符号なしのアドレス空間の境界を越えることができず、割り当てられたオブジェクトがポインターインデックス型空間の半分よりも大きくなることができないという仮定に基づいています。

inboundsgetelementptr命令に存在する場合、nusw属性も自動的に設定されます。このため、inboundsがすでに存在する場合は、テキストIRにnuswも出力されません。

inrange(Start, End)属性が存在する場合、getelementptrから派生したポインターからのロードまたはストアは、ロードまたはストアがgetelementptr式の結果から半開範囲[Start, End)外のメモリにアクセスする場合、未定義の動作をします。inrangeキーワードを持つgetelementptrから派生したポインターを含むポインター比較またはptrtoint(メモリを含むptrtointのような操作を含む)の結果は、両方のオペランドが閉範囲[Start, End]にある場合の比較を除いて、未定義です。inrangeキーワードは、現在定数getelementptr式でのみ許可されていることに注意してください。

getelementptr命令は、しばしば混乱を招きます。その動作についての詳細な洞察については、getelementptr FAQを参照してください。

例:
%aptr = getelementptr {i32, [12 x i8]}, ptr %saptr, i64 0, i32 1
%vptr = getelementptr {i32, <2 x i8>}, ptr %svptr, i64 0, i32 1, i32 1
%eptr = getelementptr [12 x i8], ptr %aptr, i64 0, i32 1
%iptr = getelementptr [10 x i32], ptr @arr, i16 0, i16 0
ポインターのベクター:

getelementptrは、その引数の1つ以上がベクターである場合、単一のアドレスではなくポインターのベクターを返します。このような場合、すべてのベクター引数は同じ数の要素を持つ必要があり、すべてスカラー引数はアドレス計算中にベクターに効果的にブロードキャストされます。

; All arguments are vectors:
;   A[i] = ptrs[i] + offsets[i]*sizeof(i8)
%A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets

; Add the same scalar offset to each pointer of a vector:
;   A[i] = ptrs[i] + offset*sizeof(i8)
%A = getelementptr i8, <4 x ptr> %ptrs, i64 %offset

; Add distinct offsets to the same pointer:
;   A[i] = ptr + offsets[i]*sizeof(i8)
%A = getelementptr i8, ptr %ptr, <4 x i64> %offsets

; In all cases described above the type of the result is <4 x ptr>

次の2つの命令は同等です。

getelementptr  %struct.ST, <4 x ptr> %s, <4 x i64> %ind1,
  <4 x i32> <i32 2, i32 2, i32 2, i32 2>,
  <4 x i32> <i32 1, i32 1, i32 1, i32 1>,
  <4 x i32> %ind4,
  <4 x i64> <i64 13, i64 13, i64 13, i64 13>

getelementptr  %struct.ST, <4 x ptr> %s, <4 x i64> %ind1,
  i32 2, i32 1, <4 x i32> %ind4, i64 13

Cコードを見てみましょう。ここで、getelementptrのベクターバージョンが意味をなします。

// Let's assume that we vectorize the following loop:
double *A, *B; int *C;
for (int i = 0; i < size; ++i) {
  A[i] = B[C[i]];
}
; get pointers for 8 elements from array B
%ptrs = getelementptr double, ptr %B, <8 x i32> %C
; load 8 elements from array B into A
%A = call <8 x double> @llvm.masked.gather.v8f64.v8p0f64(<8 x ptr> %ptrs,
     i32 8, <8 x i1> %mask, <8 x double> %passthru)

変換演算

このカテゴリの命令は変換命令(キャスト)であり、すべて単一のオペランドと型を取ります。それらはオペランドに対してさまざまなビット変換を実行します。

trunc .. to」命令

構文:
<result> = trunc <ty> <value> to <ty2>             ; yields ty2
<result> = trunc nsw <ty> <value> to <ty2>         ; yields ty2
<result> = trunc nuw <ty> <value> to <ty2>         ; yields ty2
<result> = trunc nuw nsw <ty> <value> to <ty2>     ; yields ty2
概要:

trunc」命令は、そのオペランドを型ty2に切り捨てます。

引数:

trunc」命令は、切り捨てる値と、切り捨てる型を受け取ります。両方の型は、整数型、または同じ数の整数のベクターである必要があります。valueのビットサイズは、宛先型ty2のビットサイズよりも大きい必要があります。同じサイズの型は許可されていません。

セマンティクス:

trunc」命令は、valueの上位ビットを切り捨て、残りのビットをty2に変換します。ソースサイズは宛先サイズよりも大きい必要があるため、truncno-opキャストにすることはできません。常にビットを切り捨てます。

nuwキーワードが存在し、切り捨てられたビットのいずれかがゼロ以外の場合、結果はpoison値になります。nswキーワードが存在し、切り捨てられたビットのいずれかが切り捨て結果の最上位ビットと同じでない場合、結果はpoison値になります。

例:
%X = trunc i32 257 to i8                        ; yields i8:1
%Y = trunc i32 123 to i1                        ; yields i1:true
%Z = trunc i32 122 to i1                        ; yields i1:false
%W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> ; yields <i8 8, i8 7>

zext .. to」命令

構文:
<result> = zext <ty> <value> to <ty2>             ; yields ty2
概要:

zext’命令は、そのオペランドを型ty2にゼロ拡張します。

存在する場合、nneg(非負)フラグは、オペランドが非負であることを指定します。このプロパティは、最適化パスで後でzextsextに変換するために使用される場合があります。

引数:

zext’命令は、キャストする値とキャスト先の型を取ります。両方の型は、整数型、または同じ数の整数のベクトルである必要があります。valueのビットサイズは、宛先型ty2のビットサイズよりも小さくなければなりません。

意味:

zextは、valueの上位ビットを、宛先型ty2のサイズに達するまでゼロビットで埋めます。

i1からゼロ拡張する場合、結果は常に0または1になります。

nnegフラグが設定されており、zext引数が負の場合、結果はポイズン値になります。

例:
%X = zext i32 257 to i64              ; yields i64:257
%Y = zext i1 true to i32              ; yields i32:1
%Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>

%a = zext nneg i8 127 to i16 ; yields i16 127
%b = zext nneg i8 -1 to i16  ; yields i16 poison

sext .. to’ 命令

構文:
<result> = sext <ty> <value> to <ty2>             ; yields ty2
概要:

sext’は、valueを型ty2に符号拡張します。

引数:

sext’命令は、キャストする値とキャスト先の型を取ります。両方の型は、整数型、または同じ数の整数のベクトルである必要があります。valueのビットサイズは、宛先型ty2のビットサイズよりも小さくなければなりません。

意味:

sext’命令は、valueの符号ビット(最上位ビット)を型ty2のビットサイズに達するまでコピーすることにより、符号拡張を実行します。

i1から符号拡張する場合、拡張の結果は常に-1または0になります。

例:
%X = sext i8  -1 to i16              ; yields i16   :65535
%Y = sext i1 true to i32             ; yields i32:-1
%Z = sext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>

fptrunc .. to’ 命令

構文:
<result> = fptrunc <ty> <value> to <ty2>             ; yields ty2
概要:

fptrunc’命令は、valueを型ty2に切り捨てます。

引数:

fptrunc’命令は、キャストする浮動小数点値と、キャスト先の浮動小数点型を取ります。valueのサイズは、ty2のサイズよりも大きくなければなりません。これは、fptruncを使用して*no-opキャスト*を作成できないことを意味します。

意味:

fptrunc’命令は、より大きな浮動小数点型からより小さな浮動小数点型にvalueをキャストします。この命令は、デフォルトの浮動小数点環境で実行されると想定されます。

NaN値は、通常のNaNの動作に従います。ただし、NaNペイロードが入力から伝播される(「Quieting NaN propagation」または「Unchanged NaN propagation」の場合)、結果の型に収まらないNaNペイロードの下位ビットは破棄されます。下位ビットを破棄するとすべての0のペイロードになる場合、これはシグナリングNaNとして表現できない(代わりに無限大を表す)ため、その場合「Unchanged NaN propagation」は不可能です。

例:
%X = fptrunc double 16777217.0 to float    ; yields float:16777216.0
%Y = fptrunc double 1.0E+300 to half       ; yields half:+infinity

fpext .. to’ 命令

構文:
<result> = fpext <ty> <value> to <ty2>             ; yields ty2
概要:

fpext’は、浮動小数点valueをより大きな浮動小数点値に拡張します。

引数:

fpext’命令は、キャストする浮動小数点valueと、キャスト先の浮動小数点型を取ります。ソース型は、宛先型よりも小さくなければなりません。

意味:

fpext’命令は、valueをより小さな浮動小数点型からより大きな浮動小数点型に拡張します。fpextは常にビットを変更するため、*no-opキャスト*を作成するために使用することはできません。浮動小数点キャストに対して*no-opキャスト*を作成するには、bitcastを使用してください。

NaN値は、通常のNaNの動作に従います。ただし、NaNペイロードが入力から伝播される(「Quieting NaN propagation」または「Unchanged NaN propagation」の場合)、結果のペイロードの上位ビットにコピーされ、残りの下位ビットはゼロになります。

例:
%X = fpext float 3.125 to double         ; yields double:3.125000e+00
%Y = fpext double %X to fp128            ; yields fp128:0xL00000000000000004000900000000000

fptoui .. to’ 命令

構文:
<result> = fptoui <ty> <value> to <ty2>             ; yields ty2
概要:

fptoui’は、浮動小数点valueを型ty2の符号なし整数相当に変換します。

引数:

fptoui’命令は、キャストする値(スカラーまたはベクトルの浮動小数点値である必要があります)と、キャスト先の型ty2整数型である必要があります)を取ります。tyがベクトル浮動小数点型の場合、ty2tyと同じ数の要素を持つベクトル整数型である必要があります。

意味:

fptoui’命令は、浮動小数点オペランドを最も近い(ゼロに向かって丸める)符号なし整数値に変換します。値がty2に収まらない場合、結果はポイズン値になります。

例:
%X = fptoui double 123.0 to i32      ; yields i32:123
%Y = fptoui float 1.0E+300 to i1     ; yields undefined:1
%Z = fptoui float 1.04E+17 to i8     ; yields undefined:1

fptosi .. to’ 命令

構文:
<result> = fptosi <ty> <value> to <ty2>             ; yields ty2
概要:

fptosi’命令は、浮動小数点valueを型ty2に変換します。

引数:

fptosi’命令は、キャストする値(スカラーまたはベクトルの浮動小数点値である必要があります)と、キャスト先の型ty2整数型である必要があります)を取ります。tyがベクトル浮動小数点型の場合、ty2tyと同じ数の要素を持つベクトル整数型である必要があります。

意味:

fptosi’命令は、その浮動小数点数オペランドを、最も近い(ゼロ方向への丸め)符号付き整数値に変換します。値がty2に収まらない場合、結果はpoison値になります。

例:
%X = fptosi double -123.0 to i32      ; yields i32:-123
%Y = fptosi float 1.0E-247 to i1      ; yields undefined:1
%Z = fptosi float 1.04E+17 to i8      ; yields undefined:1

uitofp .. to’命令

構文:
<result> = uitofp <ty> <value> to <ty2>             ; yields ty2
概要:

uitofp’命令は、valueを符号なし整数として扱い、その値をty2型に変換します。

nneg(非負)フラグが存在する場合、オペランドが非負であることを指定します。このプロパティは、最適化パスによって後でuitofpsitofpに変換するために使用される場合があります。

引数:

uitofp’命令は、キャストする値を受け取ります。これは、スカラーまたはベクトルの整数値でなければなりません。また、キャスト先の型ty2は、浮動小数点数型でなければなりません。tyがベクトル整数型の場合、ty2tyと同じ数の要素を持つベクトル浮動小数点型でなければなりません。

セマンティクス:

uitofp’命令は、そのオペランドを符号なし整数として解釈し、対応する浮動小数点値に変換します。値を正確に表現できない場合は、デフォルトの丸めモードを使用して丸められます。

nnegフラグが設定されており、uitofpの引数が負の場合、結果はpoison値になります。

例:
%X = uitofp i32 257 to float         ; yields float:257.0
%Y = uitofp i8 -1 to double          ; yields double:255.0

%a = uitofp nneg i32 256 to i32      ; yields float:256.0
%b = uitofp nneg i32 -256 to i32     ; yields i32 poison

sitofp .. to’命令

構文:
<result> = sitofp <ty> <value> to <ty2>             ; yields ty2
概要:

sitofp’命令は、valueを符号付き整数として扱い、その値をty2型に変換します。

引数:

sitofp’命令は、キャストする値を受け取ります。これは、スカラーまたはベクトルの整数値でなければなりません。また、キャスト先の型ty2は、浮動小数点数型でなければなりません。tyがベクトル整数型の場合、ty2tyと同じ数の要素を持つベクトル浮動小数点型でなければなりません。

セマンティクス:

sitofp’命令は、そのオペランドを符号付き整数として解釈し、対応する浮動小数点値に変換します。値を正確に表現できない場合は、デフォルトの丸めモードを使用して丸められます。

例:
%X = sitofp i32 257 to float         ; yields float:257.0
%Y = sitofp i8 -1 to double          ; yields double:-1.0

ptrtoint .. to’命令

構文:
<result> = ptrtoint <ty> <value> to <ty2>             ; yields ty2
概要:

ptrtoint’命令は、ポインタまたはポインタのベクトルvalueを、整数(または整数のベクトル)型ty2に変換します。

引数:

ptrtoint’命令は、キャストするvalueを受け取ります。これは、ポインタ型またはポインタのベクトルの値でなければなりません。また、キャスト先の型ty2は、整数型または整数のベクトル型でなければなりません。

セマンティクス:

ptrtoint’命令は、ポインタ値を整数として解釈し、その値を整数型のサイズに切り詰めるか、ゼロ拡張することにより、valueを整数型ty2に変換します。valuety2より小さい場合は、ゼロ拡張が行われます。valuety2より大きい場合は、切り捨てが行われます。同じサイズの場合は、型変更以外は何も行われません(*no-opキャスト*)。

例:
%X = ptrtoint ptr %P to i8                         ; yields truncation on 32-bit architecture
%Y = ptrtoint ptr %P to i64                        ; yields zero extension on 32-bit architecture
%Z = ptrtoint <4 x ptr> %P to <4 x i64>; yields vector zero extension for a vector of addresses on 32-bit architecture

inttoptr .. to’命令

構文:
<result> = inttoptr <ty> <value> to <ty2>[, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>]             ; yields ty2
概要:

inttoptr’命令は、整数valueをポインタ型ty2に変換します。

引数:

inttoptr’命令は、キャストする整数値と、キャスト先の型を受け取ります。これは、ポインタ型でなければなりません。

オプションの!dereferenceableメタデータは、1つのi64エントリを持つメタデータノードに対応する単一のメタデータ名<deref_bytes_node>を参照する必要があります。dereferenceableメタデータを参照してください。

オプションの!dereferenceable_or_nullメタデータは、1つのi64エントリを持つメタデータノードに対応する単一のメタデータ名<deref_bytes_node>を参照する必要があります。dereferenceable_or_nullメタデータを参照してください。

セマンティクス:

inttoptr’命令は、整数valueのサイズに応じて、ゼロ拡張または切り捨てを適用することにより、valueを型ty2に変換します。valueがポインタのサイズよりも大きい場合は、切り捨てが行われます。valueがポインタのサイズよりも小さい場合は、ゼロ拡張が行われます。同じサイズの場合は、何も行われません(*no-opキャスト*)。

例:
%X = inttoptr i32 255 to ptr           ; yields zero extension on 64-bit architecture
%Y = inttoptr i32 255 to ptr           ; yields no-op on 32-bit architecture
%Z = inttoptr i64 0 to ptr             ; yields truncation on 32-bit architecture
%Z = inttoptr <4 x i32> %G to <4 x ptr>; yields truncation of vector G to four pointers

bitcast .. to’命令

構文:
<result> = bitcast <ty> <value> to <ty2>             ; yields ty2
概要:

bitcast’命令は、ビットを変更せずにvalueを型ty2に変換します。

引数:

bitcast’命令は、キャストする値を受け取ります。これは、非集約のファーストクラス値でなければなりません。また、キャスト先の型も非集約のファーストクラス型でなければなりません。valueと変換先の型ty2のビットサイズは同一である必要があります。ソース型がポインタの場合、変換先の型も同じサイズのポインタである必要があります。この命令は、ベクトルの整数へのビット単位の変換と、他の型のベクトルへの変換をサポートします(同じサイズである限り)。

セマンティクス:

bitcast’命令は、valueを型ty2に変換します。この変換ではビットが変更されないため、常にno-opキャストとなります。この変換は、valueがメモリに格納され、型ty2として読み戻されたかのように行われます。ポインタ(またはポインタのベクタ)型は、この命令を通じて、同じアドレス空間を持つ他のポインタ(またはポインタのベクタ)型にのみ変換できます。ポインタを他の型に変換するには、最初にinttoptrまたはptrtoint命令を使用してください。

エンディアンに関連するベクタ型を含むビットキャストには注意点があります。例えば、bitcast <2 x i8> <value> to i16は、リトルエンディアンの場合、ベクタの要素ゼロをi16の最下位ビットに配置しますが、ビッグエンディアンの場合は、要素ゼロが最上位ビットに配置されます。

例:
%X = bitcast i8 255 to i8         ; yields i8 :-1
%Y = bitcast i32* %x to i16*      ; yields i16*:%x
%Z = bitcast <2 x i32> %V to i64; ; yields i64: %V (depends on endianness)
%Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*>

addrspacecast .. to」命令

構文:
<result> = addrspacecast <pty> <ptrval> to <pty2>       ; yields pty2
概要:

addrspacecast’命令は、アドレス空間nptyにあるptrvalを、アドレス空間mの型pty2に変換します。

引数:

addrspacecast’命令は、キャストするポインタまたはポインタのベクタ値と、キャスト先のポインタ型を取ります。キャスト先のポインタ型は、異なるアドレス空間を持っている必要があります。

セマンティクス:

addrspacecast’命令は、ポインタ値ptrvalを型pty2に変換します。これは、ターゲットとアドレス空間のペアに応じて、no-opキャストまたは複雑な値の変更になる可能性があります。同じアドレス空間内でのポインタ変換は、bitcast命令を使用して実行する必要があります。アドレス空間変換によって逆参照可能な結果が得られる場合、結果とオペランドの両方が同じメモリ位置を参照することに注意してください。変換には副作用があってはならず、ポインタの値をキャプチャしてはなりません。

ソースがpoisonの場合、結果はpoisonになります。

ソースがpoisonではなく、ソースと宛先の両方が整数ポインタであり、結果のポインタが逆参照可能な場合、キャストは可逆的であると想定されます(つまり、結果を元ののアドレス空間に戻してキャストすると、元のビットパターンが得られるはずです)。

例:
%X = addrspacecast ptr %x to ptr addrspace(1)
%Y = addrspacecast ptr addrspace(1) %y to ptr addrspace(2)
%Z = addrspacecast <4 x ptr> %z to <4 x ptr addrspace(3)>

その他の操作

このカテゴリの命令は、より適切な分類をすることが難しい「その他」の命令です。

icmp」命令

構文:
<result> = icmp <cond> <ty> <op1>, <op2>   ; yields i1 or <N x i1>:result
概要:

icmp’命令は、2つの整数、整数ベクタ、ポインタ、またはポインタベクタのオペランドの比較に基づいて、ブール値またはブール値のベクタを返します。

引数:

icmp’命令は、3つのオペランドを取ります。最初のオペランドは、実行する比較の種類を示す条件コードです。これは値ではなく、単なるキーワードです。可能な条件コードは次のとおりです。

  1. eq:等しい

  2. ne:等しくない

  3. ugt:符号なしで大きい

  4. uge:符号なしで大きいか等しい

  5. ult:符号なしで小さい

  6. ule:符号なしで小さいか等しい

  7. sgt:符号付きで大きい

  8. sge:符号付きで大きいか等しい

  9. slt:符号付きで小さい

  10. sle:符号付きで小さいか等しい

残りの2つの引数は、整数またはポインタまたは整数のベクタ型でなければなりません。また、それらは同一の型でなければなりません。

セマンティクス:

icmp’は、condとして指定された条件コードに従って、op1op2を比較します。実行される比較は、常にi1またはi1の結果のベクタを生成します。その結果は以下のようになります。

  1. eq:オペランドが等しい場合はtrue、それ以外の場合はfalseを生成します。符号の解釈は必要なく、実行されません。

  2. ne:オペランドが等しくない場合はtrue、それ以外の場合はfalseを生成します。符号の解釈は必要なく、実行されません。

  3. ugt:オペランドを符号なしの値として解釈し、op1op2より大きい場合はtrueを生成します。

  4. uge:オペランドを符号なしの値として解釈し、op1op2以上である場合はtrueを生成します。

  5. ult:オペランドを符号なしの値として解釈し、op1op2より小さい場合はtrueを生成します。

  6. ule:オペランドを符号なしの値として解釈し、op1op2以下である場合はtrueを生成します。

  7. sgt:オペランドを符号付きの値として解釈し、op1op2より大きい場合はtrueを生成します。

  8. sge:オペランドを符号付きの値として解釈し、op1op2以上である場合はtrueを生成します。

  9. slt:オペランドを符号付きの値として解釈し、op1op2より小さい場合はtrueを生成します。

  10. sle:オペランドを符号付きの値として解釈し、op1op2以下である場合はtrueを生成します。

オペランドがポインタ型の場合、ポインタ値は整数であるかのように比較されます。

オペランドが整数ベクタの場合、要素ごとに比較されます。結果は、比較される値と同じ数の要素を持つi1ベクタになります。それ以外の場合、結果はi1になります。

例:
<result> = icmp eq i32 4, 5          ; yields: result=false
<result> = icmp ne ptr %X, %X        ; yields: result=false
<result> = icmp ult i16  4, 5        ; yields: result=true
<result> = icmp sgt i16  4, 5        ; yields: result=false
<result> = icmp ule i16 -4, 5        ; yields: result=false
<result> = icmp sge i16  4, 5        ; yields: result=false

fcmp’ 命令

構文:
<result> = fcmp [fast-math flags]* <cond> <ty> <op1>, <op2>     ; yields i1 or <N x i1>:result
概要:

fcmp’ 命令は、オペランドの比較に基づいて、ブール値またはブール値のベクトルを返します。

オペランドが浮動小数点スカラーの場合、結果の型はブール値(i1)になります。

オペランドが浮動小数点ベクトルの場合、結果の型は比較対象のオペランドと同じ要素数を持つブール値のベクトルになります。

引数:

fcmp’ 命令は3つのオペランドを取ります。最初のオペランドは、実行する比較の種類を示す条件コードです。これは値ではなく、単なるキーワードです。可能な条件コードは以下のとおりです。

  1. false: 比較なし、常にfalseを返す

  2. oeq: 順序付けされ、等しい

  3. ogt: 順序付けされ、より大きい

  4. oge: 順序付けされ、以上

  5. olt: 順序付けされ、より小さい

  6. ole: 順序付けされ、以下

  7. one: 順序付けされ、等しくない

  8. ord: 順序付けされている (NaNがない)

  9. ueq: 順序付けされていないか、等しい

  10. ugt: 順序付けされていないか、より大きい

  11. uge: 順序付けされていないか、以上

  12. ult: 順序付けされていないか、より小さい

  13. ule: 順序付けされていないか、以下

  14. une: 順序付けされていないか、等しくない

  15. uno: 順序付けされていない (どちらかがNaN)

  16. true: 比較なし、常にtrueを返す

順序付けされているとは、どちらのオペランドもQNANではないことを意味し、順序付けされていないとは、どちらかのオペランドがQNANである可能性があることを意味します。

val1val2の各引数は、浮動小数点型、または浮動小数点型のベクトル型のいずれかである必要があります。これらは同じ型である必要があります。

セマンティクス:

fcmp’ 命令は、condとして与えられた条件コードに従って、op1op2を比較します。オペランドがベクトルの場合、ベクトルは要素ごとに比較されます。実行される各比較は、常にi1の結果を次のように生成します。

  1. false: オペランドに関係なく、常にfalseを生成します。

  2. oeq: 両方のオペランドがQNANではなく、op1op2と等しい場合、trueを生成します。

  3. ogt: 両方のオペランドがQNANではなく、op1op2より大きい場合、trueを生成します。

  4. oge: 両方のオペランドがQNANではなく、op1op2以上の場合、trueを生成します。

  5. olt: 両方のオペランドがQNANではなく、op1op2より小さい場合、trueを生成します。

  6. ole: 両方のオペランドがQNANではなく、op1op2以下の場合、trueを生成します。

  7. one: 両方のオペランドがQNANではなく、op1op2と等しくない場合、trueを生成します。

  8. ord: 両方のオペランドがQNANではない場合、trueを生成します。

  9. ueq: どちらかのオペランドがQNANであるか、op1op2と等しい場合、trueを生成します。

  10. ugt: どちらかのオペランドがQNANであるか、op1op2より大きい場合、trueを生成します。

  11. uge: どちらかのオペランドがQNANであるか、op1op2以上の場合、trueを生成します。

  12. ult: どちらかのオペランドがQNANであるか、op1op2より小さい場合、trueを生成します。

  13. ule: どちらかのオペランドがQNANであるか、op1op2以下の場合、trueを生成します。

  14. une: どちらかのオペランドがQNANであるか、op1op2と等しくない場合、trueを生成します。

  15. uno: どちらかのオペランドがQNANの場合、trueを生成します。

  16. true: オペランドに関係なく、常にtrueを生成します。

fcmp 命令は、オプションで任意の数の高速数学フラグを取ることができます。これらは、通常は安全ではない浮動小数点最適化を有効にするための最適化ヒントです。

任意の高速数学フラグのセットは、fcmp 命令で有効ですが、そのセマンティクスに影響を与えるフラグは、入力引数の値について想定を可能にするフラグ、つまりnnanninf、およびreassocのみです。詳細については、高速数学フラグを参照してください。

例:
<result> = fcmp oeq float 4.0, 5.0    ; yields: result=false
<result> = fcmp one float 4.0, 5.0    ; yields: result=true
<result> = fcmp olt float 4.0, 5.0    ; yields: result=true
<result> = fcmp ueq double 1.0, 2.0   ; yields: result=false

phi’ 命令

構文:
<result> = phi [fast-math-flags] <ty> [ <val0>, <label0>], ...
概要:

phi’ 命令は、関数を表すSSAグラフ内のφノードを実装するために使用されます。

引数:

入力値の型は、最初の型フィールドで指定されます。この後、‘phi’ 命令は、引数としてペアのリストを取り、現在のブロックの各先行基本ブロックに1つのペアがあります。 ファーストクラス型の値のみをPHIノードの値引数として使用できます。ラベルのみをラベル引数として使用できます。

基本ブロックの開始とPHI命令の間には、PHI以外の命令があってはなりません。つまり、PHI命令は基本ブロックの最初にある必要があります。

SSA形式の目的では、各入力値の使用は、対応する先行ブロックから現在のブロックへのエッジ上(ただし、同じエッジ上の「invoke’命令の戻り値の定義後)に発生すると見なされます。

オプションのfast-math-flagsマーカーは、phiに1つ以上の高速数学フラグがあることを示します。これらは、通常は安全ではない浮動小数点最適化を有効にするための最適化ヒントです。高速数学フラグは、浮動小数点スカラー型またはベクトル型、または浮動小数点スカラー型またはベクトル型の配列(任意の深さにネスト)を返すphiに対してのみ有効です。

セマンティクス:

実行時、‘phi’ 命令は、現在のブロックの直前に実行された先行基本ブロックに対応するペアで指定された論理値を想定します。

例:
Loop:       ; Infinite loop that counts from 0 on up...
  %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
  %nextindvar = add i32 %indvar, 1
  br label %Loop

select’ 命令

構文:
<result> = select [fast-math flags] selty <cond>, <ty> <val1>, <ty> <val2>             ; yields ty

selty is either i1 or {<N x i1>}
概要:

select’ 命令は、IRレベルの分岐なしで、条件に基づいて1つの値を選択するために使用されます。

引数:

select’ 命令には、条件を示す ‘i1’ 値または ‘i1’ 値のベクトルと、同じファーストクラス型の2つの値が必要です。

  1. オプションの fast-math flags マーカーは、select が1つ以上のfast-math フラグを持っていることを示します。これらは、通常は安全でない浮動小数点最適化を有効にするための最適化ヒントです。fast-math フラグは、浮動小数点スカラー型またはベクトル型、あるいは浮動小数点スカラー型またはベクトル型の配列(任意の深さまでネスト可能)を返す select に対してのみ有効です。

セマンティクス:

条件が i1 で、評価結果が 1 の場合、命令は最初の値引数を返します。それ以外の場合は、2 番目の値引数を返します。

条件が i1 のベクトルの場合、値引数は同じサイズのベクトルである必要があり、選択は要素ごとに行われます。

条件が i1 で、値引数が同じサイズのベクトルの場合、ベクトル全体が選択されます。

例:
%X = select i1 true, i8 17, i8 42          ; yields i8:17

freeze’ 命令

構文:
<result> = freeze ty <val>    ; yields ty:result
概要:

freeze’ 命令は、undef および poison 値の伝播を停止するために使用されます。

引数:

freeze’ 命令は、単一の引数を取ります。

セマンティクス:

引数が undef または poison の場合、‘freeze’ は型 ‘ty’ の任意の値(ただし固定)を返します。それ以外の場合、この命令は no-op であり、入力引数を返します。同じ ‘freeze’ 命令によって返された値のすべての使用箇所は、常に同じ値を観測することが保証されています。一方、異なる ‘freeze’ 命令は異なる値を生成する可能性があります。

undef および poison ポインタは freeze できますが、結果は非参照可能なポインタになります。詳細については、ポインタエイリアシングルール のセクションを参照してください。集約値またはベクトルが freeze される場合、オペランドは要素ごとに freeze されます。集約のパディングは、メモリに格納し、別の型でロードしない限り可視化されないため、考慮されません。

例:
%w = i32 undef
%x = freeze i32 %w
%y = add i32 %w, %w         ; undef
%z = add i32 %x, %x         ; even number because all uses of %x observe
                            ; the same value
%x2 = freeze i32 %w
%cmp = icmp eq i32 %x, %x2  ; can be true or false

; example with vectors
%v = <2 x i32> <i32 undef, i32 poison>
%a = extractelement <2 x i32> %v, i32 0    ; undef
%b = extractelement <2 x i32> %v, i32 1    ; poison
%add = add i32 %a, %a                      ; undef

%v.fr = freeze <2 x i32> %v                ; element-wise freeze
%d = extractelement <2 x i32> %v.fr, i32 0 ; not undef
%add.f = add i32 %d, %d                    ; even number

; branching on frozen value
%poison = add nsw i1 %k, undef   ; poison
%c = freeze i1 %poison
br i1 %c, label %foo, label %bar ; non-deterministic branch to %foo or %bar

call’ 命令

構文:
<result> = [tail | musttail | notail ] call [fast-math flags] [cconv] [ret attrs] [addrspace(<num>)]
           <ty>|<fnty> <fnptrval>(<function args>) [fn attrs] [ operand bundles ]
概要:

call’ 命令は、単純な関数呼び出しを表します。

引数:

この命令には、いくつかの引数が必要です。

  1. オプションの tail および musttail マーカーは、オプティマイザが末尾呼び出し最適化を実行する必要があることを示します。tail マーカーは、無視できるヒントです。musttail マーカーは、プログラムが正しく動作するためには、呼び出しが末尾呼び出しとして最適化される必要があることを意味します。これは、「disable-tail-calls」のような属性がある場合でも当てはまります。musttail マーカーは、以下の保証を提供します。

    1. 呼び出しが呼び出しグラフの再帰的なサイクルの一部である場合、無制限のスタック増加は発生しません。

    2. inalloca または preallocated 属性を持つ引数は、インプレースで転送されます。

    3. "thunk" 属性を持つ関数で musttail 呼び出しが行われ、呼び出し元と呼び出し先の両方が可変長引数を持つ場合、レジスタまたはメモリ内のプロトタイプ化されていない引数はすべて呼び出し先に転送されます。同様に、戻り値の型が void であっても、呼び出し先の戻り値は呼び出し元の呼び出し元に返されます。

    両方のマーカーは、呼び出し先が呼び出し元の allocas にアクセスしないことを暗示します。tail マーカーは、呼び出し先が呼び出し元の可変長引数にアクセスしないことも暗示します。musttail でマークされた呼び出しは、以下の追加規則に従う必要があります。

    • 呼び出しは、ret 命令、またはポインタのビットキャストに続く ret 命令の直前にある必要があります。

    • ret 命令は、呼び出しによって生成された(場合によってはビットキャストされた)値、undef、または void を返す必要があります。

    • 呼び出し元と呼び出し先の呼び出し規約は一致する必要があります。

    • 呼び出し先は、呼び出し元が可変長引数の場合のみ可変長引数でなければなりません。可変長引数でない関数を適切な可変長引数型にビットキャストすることは、可変長引数でないプレフィックスが他の規則に従う限り有効です。

    • 戻り値の型は、sret ポインタへの自動変換を行ってはいけません。

さらに、呼び出し規約が swifttailcc または tailcc でない場合

  • sret、byval、inreg、returned、inalloca など、ABI に影響を与えるすべての関数属性は一致する必要があります。

  • 呼び出し元と呼び出し先のプロトタイプは一致する必要があります。パラメータまたは戻り値の型のポインタ型は、pointee 型が異なる場合がありますが、アドレス空間は異なることはありません。

一方、呼び出し規約が swifttailcc または swiftcc の場合

  • これらの ABI に影響を与える属性のみが許可されています。sret、byval、swiftself、swiftasync。

  • プロトタイプを一致させる必要はありません。

tail でマークされた呼び出しの末尾呼び出し最適化は、以下の条件が満たされる場合に発生することが保証されています。

  • 呼び出し元と呼び出し先の両方が、呼び出し規約 fastcc または tailcc を持っている。

  • 呼び出しが末尾の位置にある(ret が呼び出しの直後に続き、ret が呼び出しの値を使用するか void である)。

  • オプション -tailcallopt が有効になっているか、llvm::GuaranteedTailCallOpttrue であるか、または呼び出し規約が tailcc である

  • プラットフォーム固有の制約が満たされている。

  1. オプションの notail マーカーは、オプティマイザが呼び出しに tail または musttail マーカーを追加しないようにする必要があることを示します。これは、呼び出しで末尾呼び出し最適化が実行されないようにするために使用されます。

  2. オプションの fast-math flags マーカーは、呼び出しが1つ以上のfast-math フラグを持っていることを示します。これらは、通常は安全でない浮動小数点最適化を有効にするための最適化ヒントです。fast-math フラグは、浮動小数点スカラー型またはベクトル型、あるいは浮動小数点スカラー型またはベクトル型の配列(任意の深さまでネスト可能)を返す呼び出しに対してのみ有効です。

  3. オプションの "cconv" マーカーは、呼び出しで使用する呼び出し規約を示します。指定されていない場合、呼び出しはデフォルトで C の呼び出し規約を使用します。呼び出しの呼び出し規約は、ターゲット関数の呼び出し規約と一致する必要があります。そうしないと、動作は未定義になります。

  4. 戻り値のオプションのパラメータ属性リスト。ここでは、「zeroext」、「signext」、および「inreg」属性のみが有効です。

  5. オプションのaddrspace属性を使用して、呼び出される関数のアドレス空間を示すことができます。指定されていない場合、datalayout文字列のプログラムアドレス空間が使用されます。

  6. ty」:呼び出し命令自体の型であり、戻り値の型でもあります。値を返さない関数はvoidとしてマークされます。

  7. fnty」:呼び出される関数のシグネチャである必要があります。引数の型は、このシグネチャによって暗示される型と一致する必要があります。関数が可変個引数でない場合、この型は省略できます。

  8. fnptrval’:呼び出される関数のポインタを含む LLVM 値。ほとんどの場合、これは直接関数呼び出しですが、間接的な call も同様に可能であり、関数値への任意のポインタを呼び出します。

  9. function args」:関数シグネチャの引数型とパラメータ属性と一致する引数リスト。すべての引数は、first class型である必要があります。関数シグネチャが関数が可変個の引数を受け入れることを示している場合、追加の引数を指定できます。

  10. オプションの関数属性リスト。

  11. オプションのオペランドバンドルリスト。

セマンティクス:

call’ 命令は、制御フローを指定された関数に転送し、その入力引数を指定された値にバインドするために使用されます。呼び出された関数の ‘ret’ 命令で、制御フローは関数呼び出しの後の命令に進み、関数の戻り値が結果引数にバインドされます。

例:
%retval = call i32 @test(i32 %argc)
call i32 (ptr, ...) @printf(ptr %msg, i32 12, i8 42)        ; yields i32
%X = tail call i32 @foo()                                    ; yields i32
%Y = tail call fastcc i32 @foo()  ; yields i32
call void %foo(i8 signext 97)

%struct.A = type { i32, i8 }
%r = call %struct.A @foo()                        ; yields { i32, i8 }
%gr = extractvalue %struct.A %r, 0                ; yields i32
%gr1 = extractvalue %struct.A %r, 1               ; yields i8
%Z = call void @foo() noreturn                    ; indicates that %foo never returns normally
%ZZ = call zeroext i32 @bar()                     ; Return value is %zero extended

llvm は、名前と引数が標準 C99 ライブラリに一致する一部の関数への呼び出しを C99 ライブラリ関数として扱い、その仮定の下で最適化を実行したり、コードを生成したりする場合があります。これは、フリースタンディング環境や C ベース以外の言語に対するより良いサポートを提供するために、将来的に変更したいと考えています。

va_arg’ 命令

構文:
<resultval> = va_arg <va_list*> <arglist>, <argty>
概要:

va_arg’ 命令は、関数呼び出しの「可変長引数」領域を介して渡された引数にアクセスするために使用されます。C の va_arg マクロを実装するために使用されます。

引数:

この命令は、va_list* の値と引数の型を受け取ります。指定された引数型の値を返し、va_list をインクリメントして次の引数を指すようにします。va_list の実際の型はターゲットに固有です。

セマンティクス:

va_arg」命令は、指定された va_list から指定された型の引数をロードし、va_list を次の引数を指すようにします。詳細については、可変引数処理の組み込み関数を参照してください。

例えば、vfprintf 関数のように、可変個の引数を受け取らない関数でこの命令を呼び出すことは合法です。

va_arg は、引数として型を受け取るため、組み込み関数ではなく LLVM 命令です。

例:

可変引数処理セクションを参照してください。

コードジェネレーターは、多くのターゲットで va_arg をまだ完全にサポートしていないことに注意してください。また、現時点では、どのターゲットでも集約型での va_arg はサポートしていません。

landingpad」命令

構文:
<resultval> = landingpad <resultty> <clause>+
<resultval> = landingpad <resultty> cleanup <clause>*

<clause> := catch <type> <value>
<clause> := filter <array constant type> <array constant>
概要:

landingpad」命令は、LLVM の例外処理システムによって、基本ブロックがランディングパッド、つまり例外が発生した場所であり、try/catch シーケンスの catch 部分にあるコードに対応することを指定するために使用されます。この命令は、関数への再入時にパーソナリティ関数によって提供される値を定義します。resultvalresultty 型を持ちます。

引数:

オプションの cleanup フラグは、ランディングパッドブロックがクリーンアップであることを示します。

clause は、句のタイプ(catch または filter)で始まり、それぞれキャッチまたはフィルタリングできる「型」を表すグローバル変数を含みます。catch 句とは異なり、filter 句は引数として配列定数を取ります。スローできないフィルターには「[0 x ptr] undef」を使用します。「landingpad」命令には、少なくとも1つの clause または cleanup フラグが含まれている必要があります。

セマンティクス:

landingpad」命令は、関数への再入時にパーソナリティ関数によって設定される値を定義し、したがって landingpad 命令の「結果型」を定義します。呼び出し規約と同様に、LLVM IR でパーソナリティ関数の結果がどのように表現されるかはターゲットに固有です。

句は上から下へと順番に適用されます。インライン化によって 2 つの landingpad 命令がマージされる場合、呼び出し元の関数の句が句のリストに追加されます。例外がスローされたためにコールスタックがアンワインドされている場合、例外は各 clause と順番に比較されます。どの句にも一致せず、cleanup フラグが設定されていない場合、アンワインドはコールスタックの上位に進みます。

landingpad 命令にはいくつかの制限があります。

  • ランディングパッドブロックは、「invoke」命令のアンワインド先となる基本ブロックです。

  • ランディングパッドブロックは、最初の非 PHI 命令として「landingpad」命令を持つ必要があります。

  • ランディングパッドブロック内には、「landingpad」命令を 1 つだけ含めることができます。

  • ランディングパッドブロックではない基本ブロックには、「landingpad」命令を含めることはできません。

例:
;; A landing pad which can catch an integer.
%res = landingpad { ptr, i32 }
         catch ptr @_ZTIi
;; A landing pad that is a cleanup.
%res = landingpad { ptr, i32 }
         cleanup
;; A landing pad which can catch an integer and can only throw a double.
%res = landingpad { ptr, i32 }
         catch ptr @_ZTIi
         filter [1 x ptr] [ptr @_ZTId]

catchpad」命令

構文:
<resultval> = catchpad within <catchswitch> [<args>*]
概要:

catchpad」命令は、LLVM の例外処理システムによって、基本ブロックがキャッチハンドラーの開始、つまりパーソナリティルーチンが例外をキャッチするために制御を転送しようとする場所であることを指定するために使用されます。

引数:

catchswitch オペランドは、常に先行ブロックの catchswitch 命令によって生成されたトークンである必要があります。これにより、各 catchpad には先行ブロックが 1 つだけあり、常に catchswitch で終了することが保証されます。

args は、これが例外の適切なハンドラーであるかどうかを知るために、パーソナリティルーチンが必要とする情報に対応します。これが例外の最初の適切なハンドラーである場合、制御は catchpad に転送されます。

resultvaltoken 型を持ち、対応する catchret および他のネストされた EH パッドと catchpad を一致させるために使用されます。

セマンティクス:

例外がスローされたためにコールスタックがアンワインドされている場合、例外は args と比較されます。一致しない場合、制御は catchpad 命令に到達しません。args の表現は、完全にターゲットおよびパーソナリティ関数に固有です。

landingpad 命令と同様に、catchpad 命令は、親基本ブロックの最初の非 phi 命令である必要があります。

catchpad およびその他の「パッド」命令によって生成および消費されるトークンの意味は、Windows 例外処理ドキュメントで説明されています。

catchpad が「入力」されたが、まだ「終了」していない場合(EH ドキュメントで説明されているように)、適切な 「funclet」バンドルを伴わない call または invoke を実行することは未定義の動作です。

例:
dispatch:
  %cs = catchswitch within none [label %handler0] unwind to caller
  ;; A catch block which can catch an integer.
handler0:
  %tok = catchpad within %cs [ptr @_ZTIi]

cleanuppad」命令

構文:
<resultval> = cleanuppad within <parent> [<args>*]
概要:

cleanuppad」命令は、LLVM の例外処理システムによって、基本ブロックがクリーンアップブロック、つまりパーソナリティルーチンがクリーンアップアクションを実行するために制御を転送しようとする場所であることを指定するために使用されます。args は、パーソナリティ関数がクリーンアップを実行するために必要とする追加情報に対応します。resultvaltoken 型を持ち、対応する cleanupretcleanuppad を一致させるために使用されます。parent 引数は、cleanuppad 命令を含む funclet のトークンです。cleanuppad が funclet の内部にない場合、このオペランドはトークン none にすることができます。

引数:

この命令は、パーソナリティ関数によって解釈される任意の値のリストを受け取ります。

セマンティクス:

例外がスローされたためにコールスタックがアンワインドされている場合、パーソナリティ関数はパーソナリティ固有の引数を使用して cleanuppad に制御を転送します。呼び出し規約と同様に、LLVM IR でパーソナリティ関数の結果がどのように表現されるかはターゲットに固有です。

cleanuppad 命令にはいくつかの制限があります。

  • クリーンアップブロックは、例外的な命令のアンワインド先となる基本ブロックです。

  • クリーンアップブロックは、最初の非 PHI 命令として「cleanuppad」命令を持つ必要があります。

  • クリーンアップブロック内には、「cleanuppad」命令を 1 つだけ含めることができます。

  • クリーンアップブロックではない基本ブロックには、「cleanuppad」命令を含めることはできません。

例:
%tok = cleanuppad within %cs []

デバッグレコード

デバッグレコードは命令と交互に現れますが、命令ではありません。デバッグ情報を定義するためだけに使用され、生成されたコードには影響しません。これらは、先頭に#を使用し、追加のインデントレベルによって命令と区別されます。例として、

%inst1 = op1 %a, %b
  #dbg_value(%inst1, !10, !DIExpression(), !11)
%inst2 = op2 %inst1, %c

これらのデバッグレコードは、以前のデバッグイントリンシックを置き換えます。--write-experimental-debuginfo=false が LLVM に渡された場合、デバッグレコードは無効になります。同じモジュール内にレコードとイントリンシックの両方が現れるのはエラーです。デバッグレコードに関する詳細については、LLVM ソースレベルデバッグドキュメントを参照してください。

組み込み関数

LLVMは「組み込み関数」の概念をサポートしています。これらの関数は、よく知られた名前とセマンティクスを持ち、特定の制限に従う必要があります。全体として、これらのイントリンシックは、言語に追加するときにLLVM内のすべての変換を変更する必要がない(またはビットコードリーダー/ライター、パーサーなど)LLVM言語の拡張メカニズムを表します。

組み込み関数名はすべて「llvm.」というプレフィックスで始まる必要があります。このプレフィックスは、LLVMで組み込み名用に予約されています。したがって、関数名はこのプレフィックスで始めることはできません。組み込み関数は常に外部関数である必要があります。組み込み関数の本体を定義することはできません。組み込み関数は、callまたはinvoke命令でのみ使用できます。組み込み関数のアドレスを取得することは違法です。また、組み込み関数はLLVM言語の一部であるため、追加された場合はここにドキュメント化する必要があります。

一部の組み込み関数はオーバーロードできます。つまり、イントリンシックは同じ操作を実行するが、異なるデータ型で実行する関数のファミリを表します。LLVMは800万を超える異なる整数型を表すことができるため、任意の整数型で組み込み関数が動作できるように、オーバーロードが一般的に使用されます。引数型または結果型の1つ以上をオーバーロードして、任意の整数型を受け入れることができます。引数型は、前の引数の型または結果型と正確に一致するように定義することもできます。これにより、複数の引数を受け入れるが、それらすべてが同じ型である必要がある組み込み関数を、単一の引数または結果に関してのみオーバーロードできます。

オーバーロードされたイントリンシックには、その関数名にエンコードされたオーバーロードされた引数型の名前があり、それぞれピリオドで区切られます。名前の接尾辞になるのは、オーバーロードされた型のみです。型が別の型と照合される引数は、そうではありません。たとえば、llvm.ctpop関数は任意の幅の整数を受け取り、まったく同じ整数幅の整数を返します。これにより、i8 @llvm.ctpop.i8(i8 %val)i29 @llvm.ctpop.i29(i29 %val)などの関数のファミリができます。戻り値の型である1つの型のみがオーバーロードされており、必要な型接尾辞は1つのみです。引数の型は戻り値の型と照合されるため、独自の型接尾辞は必要ありません。

名前のない型は、s_sとしてエンコードされます。オーバーロードされた引数型の1つに名前のない型に依存するオーバーロードされたイントリンシックには、追加の.<number>接尾辞が付きます。これにより、引数として異なる名前のない型を持つイントリンシックを区別できます。(例:llvm.ssa.copy.p0s_s.2(%42*))数値はLLVMモジュールで追跡され、モジュール内での一意の名前を保証します。2つのモジュールを一緒にリンクしている間、名前の衝突が発生する可能性があります。その場合、いずれかの名前が新しい数値を取得して変更されます。

バックエンドコード生成用のイントリンシックを定義するターゲット開発者の場合、整数型と浮動小数点型の区別のみに基づくイントリンシックのオーバーロードは、正しいコード生成のために信頼すべきではありません。このような場合、イントリンシックを定義する際のターゲットメンテナーに推奨されるアプローチは、オーバーロードに依存するのではなく、個別の整数イントリンシックとFPイントリンシックを作成することです。たとえば、llvm.target.foo(<4 x i32>)llvm.target.foo(<4 x float>)で異なるコード生成が必要な場合は、これらを異なるイントリンシックに分割する必要があります。

組み込み関数の追加方法については、LLVM拡張ガイドを参照してください。

可変引数処理イントリンシック

可変引数サポートは、LLVMではva_arg命令とこれらの3つの組み込み関数で定義されています。これらの関数は、<stdarg.h>ヘッダーファイルで定義されている同様の名前のマクロに関連しています。

これらの関数はすべて、ターゲット固有の値型「va_list」へのポインターを引数として取ります。LLVMアセンブリ言語リファレンスマニュアルでは、この型が何であるかを定義していないため、すべての変換は、使用される型に関係なくこれらの関数を処理できるように準備する必要があります。イントリンシックはオーバーロードされており、異なるアドレス空間へのポインターに使用できます。

この例は、va_arg命令と可変引数処理組み込み関数の使用方法を示しています。

; This struct is different for every platform. For most platforms,
; it is merely a ptr.
%struct.va_list = type { ptr }

; For Unix x86_64 platforms, va_list is the following struct:
; %struct.va_list = type { i32, i32, ptr, ptr }

define i32 @test(i32 %X, ...) {
  ; Initialize variable argument processing
  %ap = alloca %struct.va_list
  call void @llvm.va_start.p0(ptr %ap)

  ; Read a single integer argument
  %tmp = va_arg ptr %ap, i32

  ; Demonstrate usage of llvm.va_copy and llvm.va_end
  %aq = alloca ptr
  call void @llvm.va_copy.p0(ptr %aq, ptr %ap)
  call void @llvm.va_end.p0(ptr %aq)

  ; Stop processing of arguments.
  call void @llvm.va_end.p0(ptr %ap)
  ret i32 %tmp
}

declare void @llvm.va_start.p0(ptr)
declare void @llvm.va_copy.p0(ptr, ptr)
declare void @llvm.va_end.p0(ptr)

llvm.va_start」イントリンシック

構文:
declare void @llvm.va_start.p0(ptr <arglist>)
declare void @llvm.va_start.p5(ptr addrspace(5) <arglist>)
概要:

llvm.va_start」イントリンシックは、va_argで後で使用するために<arglist>を初期化します。

引数:

引数は、初期化するva_list要素へのポインターです。

セマンティクス:

llvm.va_start」イントリンシックは、Cで利用可能なva_startマクロのように機能します。ターゲットに依存する方法で、引数が指すva_list要素を初期化し、va_argへの次の呼び出しが、関数に渡された最初の可変引数を生成するようにします。C va_startマクロとは異なり、このイントリンシックは、コンパイラーがそれを把握できるため、関数の最後の引数を知る必要はありません。

llvm.va_end」イントリンシック

構文:
declare void @llvm.va_end.p0(ptr <arglist>)
declare void @llvm.va_end.p5(ptr addrspace(5) <arglist>)
概要:

llvm.va_end」イントリンシックは、以前にllvm.va_startまたはllvm.va_copyで初期化された<arglist>を破棄します。

引数:

引数は、破棄するva_listへのポインターです。

セマンティクス:

llvm.va_end」イントリンシックは、Cで利用可能なva_endマクロのように機能します。ターゲットに依存する方法で、引数が指すva_list要素を破棄します。llvm.va_startおよびllvm.va_copyへの呼び出しは、llvm.va_endへの呼び出しと正確に一致する必要があります。

llvm.va_copy」イントリンシック

構文:
declare void @llvm.va_copy.p0(ptr <destarglist>, ptr <srcarglist>)
declare void @llvm.va_copy.p5(ptr addrspace(5) <destarglist>, ptr addrspace(5) <srcarglist>)
概要:

llvm.va_copy」イントリンシックは、ソース引数リストからコピー先の引数リストに現在の引数位置をコピーします。

引数:

最初の引数は、初期化するva_list要素へのポインターです。2番目の引数は、コピー元のva_list要素へのポインターです。2つの引数のアドレス空間は一致する必要があります。

セマンティクス:

llvm.va_copy」イントリンシックは、Cで利用可能なva_copyマクロのように機能します。ターゲットに依存する方法で、ソースva_list要素をコピー先のva_list要素にコピーします。このイントリンシックは、``llvm.va_start``イントリンシックが任意に複雑になり、たとえばメモリ割り当てが必要になる可能性があるため、必要です。

正確なガベージコレクションイントリンシック

正確なガベージコレクション(GC)に対するLLVMのサポートでは、フロントエンドが適切なイントリンシック呼び出しを含むコードを生成し、これらのイントリンシックをターゲットコレクターに適した方法で下げ方を知っている適切なGC戦略を選択する必要があります。

これらの組み込み関数は、スタック上のGCルートの識別や、読み取りおよび書き込みバリアを必要とするガベージコレクタの実装を可能にします。型安全なガベージコレクション言語のフロントエンドは、これらの組み込み関数を生成して、LLVMガベージコレクタを利用する必要があります。詳細については、LLVMでのガベージコレクションを参照してください。

LLVMは、コンパイルされたコードにおけるガベージコレクションセーフポイントを記述するための、2つ目の実験的な組み込み関数セットを提供します。これらの組み込み関数は、llvm.gcroot組み込み関数の代替ですが、読み取りおよび書き込みバリア用の組み込み関数と互換性があります。アプローチの違いは、LLVMでのガベージコレクションのドキュメントで説明されています。組み込み関数自体は、LLVMにおけるガベージコレクションセーフポイントで説明されています。

llvm.gcroot’ 組み込み関数

構文:
declare void @llvm.gcroot(ptr %ptrloc, ptr %metadata)
概要:

llvm.gcroot’ 組み込み関数は、コードジェネレータへのGCルートの存在を宣言し、それに関連付けるいくつかのメタデータを許可します。

引数:

最初の引数は、ルートポインタを含むスタックオブジェクトのアドレスを指定します。2番目のポインタ(定数またはグローバル値アドレスのいずれかでなければなりません)には、ルートに関連付けられるメタデータが含まれています。

セマンティクス:

ランタイムでは、この組み込み関数の呼び出しは、「ptrloc」の場所にヌルポインタを格納します。コンパイル時には、コードジェネレータは、ランタイムがGCセーフポイントでポインタを見つけられるように情報を生成します。‘llvm.gcroot’ 組み込み関数は、GCアルゴリズムを指定する関数でのみ使用できます。

llvm.gcread’ 組み込み関数

構文:
declare ptr @llvm.gcread(ptr %ObjPtr, ptr %Ptr)
概要:

llvm.gcread’ 組み込み関数は、ヒープロケーションからの参照の読み取りを識別し、読み取りバリアを必要とするガベージコレクタの実装を可能にします。

引数:

2番目の引数は、読み取るアドレスです。これはガベージコレクタから割り当てられたアドレスである必要があります。最初のオブジェクトは、言語ランタイムで必要な場合、参照されたオブジェクトの先頭へのポインタです(それ以外の場合はnull)。

セマンティクス:

llvm.gcread’ 組み込み関数は、ロード命令と同じセマンティクスを持ちますが、必要に応じて、ガベージコレクタランタイムによって大幅に複雑なコードに置き換えられる可能性があります。‘llvm.gcread’ 組み込み関数は、GCアルゴリズムを指定する関数でのみ使用できます。

llvm.gcwrite’ 組み込み関数

構文:
declare void @llvm.gcwrite(ptr %P1, ptr %Obj, ptr %P2)
概要:

llvm.gcwrite’ 組み込み関数は、ヒープロケーションへの参照の書き込みを識別し、書き込みバリア(世代別または参照カウントコレクタなど)を必要とするガベージコレクタの実装を可能にします。

引数:

最初の引数は格納する参照、2番目の引数は格納先のオブジェクトの先頭、3番目の引数は格納先のObjのフィールドのアドレスです。ランタイムがオブジェクトへのポインタを必要としない場合、Objはnullにすることができます。

セマンティクス:

llvm.gcwrite’ 組み込み関数は、ストア命令と同じセマンティクスを持ちますが、必要に応じて、ガベージコレクタランタイムによって大幅に複雑なコードに置き換えられる可能性があります。‘llvm.gcwrite’ 組み込み関数は、GCアルゴリズムを指定する関数でのみ使用できます。

llvm.experimental.gc.statepoint’ 組み込み関数

構文:
declare token
  @llvm.experimental.gc.statepoint(i64 <id>, i32 <num patch bytes>,
                 ptr elementtype(func_type) <target>,
                 i64 <#call args>, i64 <flags>,
                 ... (call parameters),
                 i64 0, i64 0)
概要:

statepoint組み込み関数は、ランタイムで解析可能な呼び出しを表します。

オペランド:

‘id’ オペランドは、生成されたスタックマップの ID フィールドとして報告される定数整数です。 LLVMはこのパラメータを解釈せず、その意味はstatepointユーザが決定します。 LLVMは、statepoint呼び出しを含むコードを自由に複製でき、これにより、字句ごとのstatepoint呼び出しごとに一意の ‘id’ を持っていたIRが、そうでないIRに変換される可能性があることに注意してください。

‘num patch bytes’ がゼロ以外の場合、statepointに対応する call 命令は出力されず、LLVMはその代わりに ‘num patch bytes’ バイトの nop を出力します。 LLVMは、関数引数を準備し、呼び出し規約に従って関数の戻り値を取得するコードを出力します。前者は nop シーケンスの前、後者は nop シーケンスの後です。 ユーザは、生成されたマシンコードを実行する前に、ランタイム固有の呼び出しシーケンスで ‘num patch bytes’ バイトの nop をパッチする必要があることが予想されます。 nop シーケンスのアライメントに関する保証はありません。 LLVMのスタックマップとパッチポイントとは異なり、statepointにはシャドウバイトの概念がありません。意味的には、statepointは依然として ‘target’ への呼び出しまたは呼び出しを表しており、パッチ後の nop シーケンスは ‘target’ への呼び出しまたは呼び出しと同等の操作を表すことが期待されることに注意してください。

‘target’ オペランドは、実際に呼び出される関数です。オペランドには、ターゲットの関数型を指定するelementtype属性が必要です。ターゲットは、シンボリックなLLVM関数として、またはポインタ型の任意のValueとして指定できます。関数型は、呼び出し先のシグネチャと ‘call parameters’ 引数の型と一致する必要があることに注意してください。

‘#call args’ オペランドは、実際の呼び出しへの引数の数です。これは、‘call parameters’ 可変長セクションで渡される引数の数と正確に一致する必要があります。

‘flags’ オペランドは、statepointに関する追加情報を指定するために使用されます。これは現在、特定の statepoint を GC トランジションとしてマークするためにのみ使用されます。このオペランドは、次のレイアウトの 64 ビット整数です。ここで、ビット 0 が最下位ビットです。

ビット#

使用法

0

statepoint が GC トランジションの場合は設定し、それ以外の場合はクリアします。

1-63

将来の使用のために予約されています。クリアする必要があります。

‘call parameters’ 引数は、呼び出しターゲットに渡す必要がある引数です。それらは、指定された呼び出し規約に従って下げられ、それ以外の場合は通常の call 命令のように処理されます。引数の数は、‘# call args’ で指定されたものと正確に一致する必要があります。型は ‘target’ のシグネチャと一致する必要があります。

‘call parameter’ 属性の後に、2つの ‘i64 0’ 定数が続きます。これらは元々 ‘gc transition parameter’ 引数と ‘deopt parameter’ 引数の長さのプレフィックスでしたが、これらのパラメータセットの役割は、対応するオペランドバンドルに完全に置き換えられました。将来の改訂では、これらの冗長な引数は削除されます。

セマンティクス:

statepointは、すべてのメモリを読み書きすると想定されます。その結果、statepointを越えてメモリ操作を並べ替えることはできません。statepointを ‘readonly’ または ‘readnone’ としてマークすることは違法です。

静的にstatepointから到達可能な場所で、statepointの ‘gc pointer’ 引数に対してメモリ操作を実行できないことに注意してください。代わりに、明示的に再配置された値(gc.relocateから)を使用する必要があります。

llvm.experimental.gc.result’ 組み込み関数

構文:
declare type
  @llvm.experimental.gc.result(token %statepoint_token)
概要:

gc.result は、gc.statepoint に置き換えられた元の call 命令の結果を抽出します。gc.result 組み込み関数は、実装上の制限により、実際には3つの組み込み関数のファミリです。戻り値の型以外は、セマンティクスは同じです。

オペランド:

最初で唯一の引数は、この gc.result が一部となるセーフポイントシーケンスを開始する gc.statepoint です。これを汎用トークンとして型付けしているにもかかわらず、gc.statepoint によって定義された値のみがここで有効です。

セマンティクス:

gc.result は、statepoint の呼び出しターゲットの戻り値を表します。gc.result の型は、ターゲットの型と完全に一致する必要があります。呼び出しターゲットが void を返す場合、gc.result は存在しません。

gc.result は、'readnone' の純粋関数としてモデル化されます。これは、gc.statepoint で表される前の呼び出しの戻り値の射影に過ぎないため、副作用はありません。

llvm.experimental.gc.relocate’ 組み込み関数

構文:
declare <pointer type>
  @llvm.experimental.gc.relocate(token %statepoint_token,
                                 i32 %base_offset,
                                 i32 %pointer_offset)
概要:

gc.relocate は、セーフポイントにおけるポインタの、再配置される可能性のある値を返します。

オペランド:

最初の引数は、この gc.relocation が一部であるセーフポイントシーケンスを開始する gc.statepoint です。これをジェネリックトークンとして型指定しているにもかかわらず、gc.statepoint によって定義された値 *のみ* がここで有効です。

2番目と3番目の引数は、対応するステートポイントの gc-live オペランドバンドルへのインデックスです。

2番目の引数は、再配置されるポインタの割り当てを指定するインデックスです。関連付けられた値は、再配置されるポインタが関連付けられているオブジェクト内にある必要があります。オプティマイザーは、実際のベースポインタを別の内部派生ポインタに置き換えない限り、報告される内部派生ポインタを *どれでも* 自由に変更できます。コレクターは、ベースポインタオペランドがそのように構築された場合に、実際のベースポインタのままであることに依存できます。

3番目の引数は、再配置される(可能性のある)派生ポインタを指定するインデックスです。ベースポインタが再配置されている場合に *のみ* 、このインデックスが2番目の引数と同じになることは有効です。

セマンティクス:

gc.relocate の戻り値は、引数で指定されたポインタの、再配置される可能性のある値です。返されたポインタの値と gc.statepoint の引数との関係は、a) 同じオフセットを持つ同じソース言語オブジェクトを指していること、および b) 新しく再配置されたポインタの「基づく」関係が、再配置されていないポインタの射影であること以外は、不特定です。特に、返されるポインタの整数値は不特定です。

gc.relocate は、readnone の純粋関数としてモデル化されます。これは、gc.statepoint によってモデル化された実際の呼び出し中に行われた作業に関する情報を抽出する単なる方法であるため、副作用はありません。

llvm.experimental.gc.get.pointer.base’ 組み込み関数

構文:
declare <pointer type>
  @llvm.experimental.gc.get.pointer.base(
    <pointer type> readnone nocapture %derived_ptr)
    nounwind willreturn memory(none)
概要:

派生ポインタに対する gc.get.pointer.base は、そのベースポインタを返します。

オペランド:

唯一の引数は、オブジェクトのベースからの不明なオフセットを持つ、いくつかのオブジェクトに基づいているポインタです。

セマンティクス:

この組み込み関数は、GC の抽象マシンモデルで、任意の派生ポインタのベースポインタを表すために使用されます。

この組み込み関数は、RewriteStatepointsForGC パスによって、この呼び出しサイトのすべての使用を、そのベースポインタ値からの派生ポインタのオフセットに置き換えることでインライン化されます。置換は、明示的なステートポイントモデルへの低レベル化の一部として行われます。

戻りポインタの型は、パラメータの型と同じである必要があります。

llvm.experimental.gc.get.pointer.offset’ 組み込み関数

構文:
declare i64
  @llvm.experimental.gc.get.pointer.offset(
    <pointer type> readnone nocapture %derived_ptr)
    nounwind willreturn memory(none)
概要:

派生ポインタに対する gc.get.pointer.offset は、そのベースポインタからのオフセットを返します。

オペランド:

唯一の引数は、オブジェクトのベースからの不明なオフセットを持つ、いくつかのオブジェクトに基づいているポインタです。

セマンティクス:

この組み込み関数は、GC の抽象マシンモデルで、ベースポインタからの任意の派生ポインタのオフセットを表すために使用されます。

この組み込み関数は、RewriteStatepointsForGC パスによって、この呼び出しサイトのすべての使用を、そのベースポインタ値からの派生ポインタのオフセットに置き換えることでインライン化されます。置換は、明示的なステートポイントモデルへの低レベル化の一部として行われます。

基本的に、この呼び出しは、派生ポインタとそのベースポインタ(‘llvm.experimental.gc.get.pointer.base’ 組み込み関数 を参照)の両方を ptrtoint にキャストした際の差を計算します。ただし、RewriteStatepointsForGC パスの外で行われたこのキャストは、抽象モデルから明示的な物理モデルへのさらなる低レベル化のために、ポインタが失われる可能性があります。

コードジェネレーターの組み込み関数

これらの組み込み関数は、コードジェネレーターのサポートによってのみ実装できる特別な機能を公開するために LLVM によって提供されます。

llvm.returnaddress’ 組み込み関数

構文:
declare ptr @llvm.returnaddress(i32 <level>)
概要:

llvm.returnaddress’ 組み込み関数は、現在の関数またはその呼び出し元のいずれかの戻りアドレスを示すターゲット固有の値を計算しようとします。

引数:

この組み込み関数への引数は、どのアドレスを返す関数を示すかを示します。ゼロは呼び出し元の関数、1 はその呼び出し元などを意味します。引数は、定数整数値である *必要* があります。

セマンティクス:

llvm.returnaddress’ 組み込み関数は、指定された呼び出しフレームの戻りアドレスを示すポインタを返すか、識別できない場合はゼロを返します。この組み込み関数によって返される値は、ゼロ以外の引数では誤っているか 0 になる可能性が高いため、デバッグ目的でのみ使用する必要があります。

この組み込み関数を呼び出しても、関数のインライン化やその他のアグレッシブな変換が妨げられないことに注意してください。そのため、返される値は、明らかなソース言語の呼び出し元の値ではない可能性があります。

llvm.addressofreturnaddress’ 組み込み関数

構文:
declare ptr @llvm.addressofreturnaddress()
概要:

llvm.addressofreturnaddress’ 組み込み関数は、現在の関数の戻りアドレスが格納されているスタックフレーム内の場所へのターゲット固有のポインタを返します。

セマンティクス:

この組み込み関数を呼び出しても、関数のインライン化やその他のアグレッシブな変換が妨げられないことに注意してください。そのため、返される値は、明らかなソース言語の呼び出し元の値ではない可能性があります。

この組み込み関数は、x86 および aarch64 に対してのみ実装されています。

llvm.sponentry’ 組み込み関数

構文:
declare ptr @llvm.sponentry()
概要:

llvm.sponentry’ 組み込み関数は、この組み込み関数を呼び出す現在の関数のエントリでのスタックポインタ値を返します。

セマンティクス:

この組み込み関数は、AArch64 および ARM でのみ検証されることに注意してください。

llvm.frameaddress’ 組み込み関数

構文:
declare ptr @llvm.frameaddress(i32 <level>)
概要:

llvm.frameaddress’ 組み込み関数は、指定されたスタックフレームのターゲット固有のフレームポインタ値を返そうとします。

引数:

この組み込み関数への引数は、どのアドレスを返す関数を示すかを示します。ゼロは呼び出し元の関数、1 はその呼び出し元などを意味します。引数は、定数整数値である *必要* があります。

セマンティクス:

llvm.frameaddress’ 組み込み関数は、指定された呼び出しフレームのフレームアドレスを示すポインタを返すか、識別できない場合はゼロを返します。この組み込み関数によって返される値は、ゼロ以外の引数では誤っているか 0 になる可能性が高いため、デバッグ目的でのみ使用する必要があります。

この組み込み関数を呼び出しても、関数のインライン化やその他のアグレッシブな変換が妨げられないことに注意してください。そのため、返される値は、明らかなソース言語の呼び出し元の値ではない可能性があります。

llvm.swift.async.context.addr’ 組み込み関数

構文:
declare ptr @llvm.swift.async.context.addr()
概要:

llvm.swift.async.context.addr’ 組み込み関数は、Swift 実行の非同期コンテキストを含む拡張フレームレコードの一部へのポインタを返します。

セマンティクス:

呼び出し元に swiftasync パラメータがある場合、その引数は最初に返されたアドレスに格納されます。そうでない場合は、null に初期化されます。

llvm.localescape’ および ‘llvm.localrecover’ イントリンシック

構文:
declare void @llvm.localescape(...)
declare ptr @llvm.localrecover(ptr %func, ptr %fp, i32 %idx)
概要:

llvm.localescape’ イントリンシックは、静的 alloca のコレクションのオフセットをエスケープし、‘llvm.localrecover’ イントリンシックは、それらのオフセットをライブのフレームポインタに適用して、アロケーションのアドレスを回復します。オフセットは、llvm.localescape の呼び出し元のフレームレイアウト中に計算されます。

引数:

llvm.localescape’ へのすべての引数は、静的 alloca へのポインタまたは静的 alloca のキャストである必要があります。各関数は ‘llvm.localescape’ を一度だけ呼び出すことができ、エントリブロックからのみ呼び出すことができます。

llvm.localrecover’ への func 引数は、現在のモジュールで定義された関数への定数ビットキャストされたポインタである必要があります。コードジェネレータは、他のモジュールで定義された関数のフレームアロケーションオフセットを決定できません。

llvm.localrecover’ への fp 引数は、現在ライブのコールフレームのフレームポインタである必要があります。‘llvm.localaddress’ の戻り値は、そのような値を生成する1つの方法ですが、さまざまなランタイムもプラットフォーム固有の方法で適切なポインタを公開しています。

llvm.localrecover’ への idx 引数は、‘llvm.localescape’ に渡されたどの alloca を回復するかを示します。これはゼロベースのインデックスです。

セマンティクス:

これらのイントリンシックを使用すると、関数のグループが、1つの親関数のローカルスタック割り当てのセットへのアクセスを共有できます。親関数は、関数エントリブロックから ‘llvm.localescape’ イントリンシックを一度呼び出すことができ、子関数は ‘llvm.localrecover’ を使用して、エスケープされた alloca にアクセスできます。インライン化は、エスケープされた alloca が割り当てられる場所を変更するため、‘llvm.localescape’ イントリンシックはインライン化をブロックします。これは ‘llvm.localrecover’ を使用する試みを壊します。

llvm.seh.try.begin’ および ‘llvm.seh.try.end’ イントリンシック

構文:
declare void @llvm.seh.try.begin()
declare void @llvm.seh.try.end()
概要:

llvm.seh.try.begin’ および ‘llvm.seh.try.end’ イントリンシックは、Windows SEH 非同期例外処理の _try 領域の境界をマークします。

セマンティクス:

C関数が Windows SEH 非同期例外オプション (-feh_asynch (別名 MSVC -EHa)) でコンパイルされると、これらの 2 つのイントリンシックが _try 境界をマークし、境界を越えて潜在的な例外が移動するのを防ぐために注入されます。一連の操作は、volatile ロードを介してリーフ入力を読み取り、volatile ストアを介してルート出力を書き込むことで、この領域に限定できます。

llvm.seh.scope.begin’ および ‘llvm.seh.scope.end’ イントリンシック

構文:
declare void @llvm.seh.scope.begin()
declare void @llvm.seh.scope.end()
概要:

llvm.seh.scope.begin’ および ‘llvm.seh.scope.end’ イントリンシックは、Windows SEH 非同期例外処理 (MSVC オプション -EHa) の CPP オブジェクトのライフタイムの境界をマークします。

セマンティクス:

LLVM の通常の例外処理表現は、EH クリーンアップとハンドラーを invoke``s のみに関連付けます。通常、これはコールサイトのみに対応します。任意の障害発生命令をサポートするには、任意の命令の現在の EH スコープを回復できる必要があります。障害が発生する可能性のある LLVM のすべての操作を、潜在的にスローする新しいイントリンシックの ``invoke`` に変換すると、多数のイントリンシックを追加する必要があり、それらの操作の最適化が妨げられ、多数の追加の基本ブロックが導入されるため、コンパイルが遅くなります。これらのイントリンシックは、非自明なデストラクタを持つローカル C++ オブジェクトなどのクリーンアップによって保護される領域をマークするために代わりに使用できます。llvm.seh.scope.begin は領域の開始をマークするために使用されます。これは常に invoke で呼び出され、巻き戻しブロックは領域内の潜在的にスローする命令に対する目的の巻き戻し先となります。llvm.seh.scope.end は、スコープが終了し、EH クリーンアップが不要になったとき (デストラクタが呼び出されるためなど) をマークするために使用されます。

llvm.read_register’、‘llvm.read_volatile_register’ および ‘llvm.write_register’ イントリンシック

構文:
declare i32 @llvm.read_register.i32(metadata)
declare i64 @llvm.read_register.i64(metadata)
declare i32 @llvm.read_volatile_register.i32(metadata)
declare i64 @llvm.read_volatile_register.i64(metadata)
declare void @llvm.write_register.i32(metadata, i32 @value)
declare void @llvm.write_register.i64(metadata, i64 @value)
!0 = !{!"sp\00"}
概要:

llvm.read_register’、‘llvm.read_volatile_register’、および ‘llvm.write_register’ イントリンシックは、指定されたレジスタへのアクセスを提供します。レジスタは、コンパイル対象のアーキテクチャで有効である必要があります。型は、読み取るレジスタと互換性がある必要があります。

セマンティクス:

llvm.read_register’ および ‘llvm.read_volatile_register’ イントリンシックは、可能な限りレジスタの現在の値を返します。‘llvm.write_register’ イントリンシックは、可能な限りレジスタの現在の値を設定します。

llvm.read_volatile_register’ の呼び出しは、副作用があり、毎回異なる値が返される可能性があると想定されます (タイマーレジスタなど)。

これは、OS カーネルを含むベアメタルプログラムで一般的なように、常に特定のレジスタにマッピングする必要がある名前付きレジスタグローバル変数を実装するのに役立ちます。

コンパイラは、レジスタの可用性や、インラインアセンブリを含む周囲のコードでの使用済みレジスタのチェックを行いません。そのため、割り当て可能なレジスタはサポートされていません。

警告: 現在のところ、選択されたアーキテクチャ (ARM、AArch64、PowerPC および x86_64) のスタックポインタでのみ機能します。他のレジスタのサポート、さらには割り当て可能なレジスタのサポートには、かなりの作業が必要です。

llvm.stacksave’ イントリンシック

構文:
declare ptr @llvm.stacksave.p0()
declare ptr addrspace(5) @llvm.stacksave.p5()
概要:

llvm.stacksave’ イントリンシックは、llvm.stackrestore で使用するために、関数のスタックの現在の状態を記憶するために使用されます。これは、C99 のスコープ付き自動可変サイズ配列のような言語機能を実装するのに役立ちます。

セマンティクス:

このイントリンシックは、llvm.stackrestore に渡すことができる不透明なポインタ値を返します。 llvm.stacksave から保存された値を使用して llvm.stackrestore イントリンシックが実行されると、llvm.stacksave イントリンシックが実行されたときのスタックの状態に、スタックの状態が効果的に復元されます。実際には、これは、llvm.stacksave が実行された後に割り当てられた alloca ブロックをスタックからポップします。アドレス空間は、通常、alloca アドレス空間 である必要があります。

llvm.stackrestore’ イントリンシック

構文:
declare void @llvm.stackrestore.p0(ptr %ptr)
declare void @llvm.stackrestore.p5(ptr addrspace(5) %ptr)
概要:

llvm.stackrestore’ イントリンシックは、対応する llvm.stacksave イントリンシックが実行されたときの関数のスタックの状態に、スタックの状態を復元するために使用されます。これは、C99 のスコープ付き自動可変サイズ配列のような言語機能を実装するのに役立ちます。アドレス空間は、通常、alloca アドレス空間 である必要があります。

セマンティクス:

llvm.stacksave の説明を参照してください。

llvm.get.dynamic.area.offset’ イントリンシック

構文:
declare i32 @llvm.get.dynamic.area.offset.i32()
declare i64 @llvm.get.dynamic.area.offset.i64()
概要:

llvm.get.dynamic.area.offset.*」組み込み関数群は、ネイティブスタックポインタから、呼び出し元のスタック上の最新の動的 alloca のアドレスまでのオフセットを取得するために使用されます。これらの組み込み関数は、最新の動的 alloca へのポインタを取得するために、llvm.stacksave と組み合わせて使用することを意図しています。これは、例えば AddressSanitizer のスタックアンポイズニングルーチンなどで役立ちます。

セマンティクス:

これらの組み込み関数は、呼び出し元のスタック上で alloca によって割り当てられた、最新の動的 alloca のアドレスを取得するために使用できる、非負の整数値を返します。特に、スタックが下方向に成長するターゲットの場合、このオフセットをネイティブスタックポインタに加算すると、最新の動的 alloca のアドレスを取得できます。スタックが上方向に成長するターゲットの場合、状況は少し複雑になります。この値をスタックポインタから減算すると、最新の動的 alloca の終端の 1 つ先のアドレスを取得することになります。

ほとんどのターゲットでは、llvm.get.dynamic.area.offset <int_get_dynamic_area_offset> は単にゼロを返しますが、PowerPC や PowerPC64 など、コンパイル時に既知の定数値を返すものもあります。

llvm.get.dynamic.area.offset の戻り値の型は、ターゲットのデフォルトアドレス空間(アドレス空間 0)のポインタ型と一致する必要があります。

llvm.prefetch」組み込み関数

構文:
declare void @llvm.prefetch(ptr <address>, i32 <rw>, i32 <locality>, i32 <cache type>)
概要:

llvm.prefetch」組み込み関数は、サポートされている場合、プリフェッチ命令を挿入するためのコードジェネレーターへのヒントです。それ以外の場合は、noop(何もしない)となります。プリフェッチはプログラムの動作には影響を与えませんが、パフォーマンス特性を変える可能性があります。

引数:

address はプリフェッチされるアドレス、rw はフェッチが読み取り(0)または書き込み(1)のどちらであるかを決定する指定子、locality は一時的な局所性を指定する指定子で、(0) - 局所性なし、から (3) - 非常に局所的でキャッシュに保持する、の範囲です。cache type は、プリフェッチがデータ(1)または命令(0)キャッシュのどちらで実行されるかを指定します。rwlocality、および cache type 引数は、定数整数である必要があります。

セマンティクス:

この組み込み関数は、プログラムの動作を変更しません。特に、プリフェッチはトラップせず、値を生成しません。この組み込み関数をサポートするターゲットでは、プリフェッチは、パフォーマンスを向上させるためにプロセッサキャッシュにヒントを提供できます。

llvm.pcmarker」組み込み関数

構文:
declare void @llvm.pcmarker(i32 <id>)
概要:

llvm.pcmarker」組み込み関数は、コード領域内のプログラムカウンタ(PC)をシミュレータやその他のツールにエクスポートする方法です。この方法はターゲット固有ですが、マーカーがエクスポートされたシンボルを使用してマーカーの PC を送信することが期待されています。マーカーは、最適化後に特定の命令と一緒に残ることを保証しません。マーカーの存在が最適化を阻害する可能性があります。意図された用途は、シミュレーション実行の相関を可能にするために、最適化後に挿入することです。

引数:

id は、マーカーを識別する数値 ID です。

セマンティクス:

この組み込み関数は、プログラムの動作を変更しません。この組み込み関数をサポートしないバックエンドは、それを無視する場合があります。

llvm.readcyclecounter」組み込み関数

構文:
declare i64 @llvm.readcyclecounter()
概要:

llvm.readcyclecounter」組み込み関数は、それをサポートするターゲットで、サイクルカウンタレジスタ(または同様の低レイテンシ、高精度クロック)へのアクセスを提供します。X86 では、RDTSC にマッピングされる必要があります。Alpha では、RPCC にマッピングされる必要があります。バックアップカウンタはすぐにオーバーフローする(alpha では約 9 秒程度)ため、これは小さなタイミングに使用する必要があります。

セマンティクス:

直接サポートされている場合、サイクルカウンタの読み取りはメモリを変更しないはずです。実装は、アプリケーション固有の値またはシステム全体の値のどちらかを返すことができます。サポートのないバックエンドでは、これは定数 0 に削減されます。

ランタイムサポートは、コードが実行されている特権レベルとホストプラットフォームによって条件付きになる場合があることに注意してください。

llvm.clear_cache」組み込み関数

構文:
declare void @llvm.clear_cache(ptr, ptr)
概要:

llvm.clear_cache」組み込み関数は、プロセッサの実行ユニットに対して、指定された範囲の変更の可視性を保証します。統合されていない命令キャッシュとデータキャッシュを持つターゲットでは、実装は命令キャッシュをフラッシュします。

セマンティクス:

コヒーレントな命令キャッシュとデータキャッシュを持つプラットフォーム(例えば x86)では、この組み込み関数は nop(何もしない)です。コヒーレントでない命令キャッシュとデータキャッシュを持つプラットフォーム(例えば ARM、MIPS)では、キャッシュのフラッシュに特別な特権が必要な場合、組み込み関数は適切な命令またはシステムコールに削減されます。

デフォルトの動作は、ランタイムライブラリから __clear_cache への呼び出しを発行することです。

この組み込み関数は、命令パイプラインを空にしません。現在の関数の変更は、組み込み関数の範囲外です。

llvm.instrprof.increment」組み込み関数

構文:
declare void @llvm.instrprof.increment(ptr <name>, i64 <hash>,
                                       i32 <num-counters>, i32 <index>)
概要:

llvm.instrprof.increment」組み込み関数は、インストルメンテーションベースのプロファイリングで使用するためにフロントエンドによって発行できます。これらは、-instrprof パスによって、ランタイム時のプログラムの実行回数を生成するために削減されます。

引数:

最初の引数は、インストルメント化されているエンティティの名前を含むグローバル変数へのポインタです。これは一般的に、カウンタセットのマングルされた関数名である必要があります。

2 番目の引数は、プロファイルデータのコンシューマがインストルメント化されたソースへの変更を検出するために使用できるハッシュ値であり、3 番目の引数は、name に関連付けられたカウンタの数です。hash または num-counters が、同じ名前を参照する instrprof.increment の 2 つのインスタンス間で異なる場合はエラーになります。

最後の引数は、name のどのカウンタをインクリメントする必要があるかを示します。これは 0 から num-counters の間の値である必要があります。

セマンティクス:

この組み込み関数は、プロファイリングカウンタのインクリメントを表します。これにより、-instrprof パスは、適切なデータ構造と、コンパイラランタイムによって書き出すことができ、llvm-profdata ツールを介して消費できる形式で、適切な値をインクリメントするコードを生成します。

この組み込み関数は、-ctx-instr-lower パスによるコンテキストプロファイリングの場合、異なる方法で削減されます。ここで

  • エントリ基本ブロックのインクリメントカウンタは、コンパイラ rt への呼び出しとして削減され、__llvm_ctx_profile_start_context または __llvm_ctx_profile_get_context のいずれかになります。どちらも、カウンタインクリメントが発生するバッファを含むコンテキストオブジェクトへのポインタを返します。コンパイラ rt によって返されるポインタ値には、LSB が設定されている場合があります。カウンタインクリメントは、LSB がクリアされたアドレスからのオフセットで発生します。

  • llvm.instrprof.increment[.step] の他のすべての削減はそのコンテキスト内で発生します。

  • コンテキストは関数のローカル値であると想定され、LLVM で処理する必要がある同時実行に関する懸念はありません。

llvm.instrprof.increment.step」組み込み関数

構文:
declare void @llvm.instrprof.increment.step(ptr <name>, i64 <hash>,
                                            i32 <num-counters>,
                                            i32 <index>, i64 <step>)
概要:

llvm.instrprof.increment.step’ 組み込み関数は、 ‘llvm.instrprof.increment’ 組み込み関数の拡張であり、インクリメントのステップを指定するための5番目の引数が追加されています。

引数:

最初の4つの引数は、 ‘llvm.instrprof.increment’ 組み込み関数と同じです。

最後の引数は、カウンタ変数のインクリメント値を指定します。

セマンティクス:

llvm.instrprof.increment’ 組み込み関数の説明を参照してください。

llvm.instrprof.callsite’ 組み込み関数

構文:
declare void @llvm.instrprof.callsite(ptr <name>, i64 <hash>,
                                      i32 <num-counters>,
                                      i32 <index>, ptr <callsite>)
概要:

llvm.instrprof.callsite’ 組み込み関数は、「偽」の呼び出し先(別の組み込み関数やアセンブリなど)への呼び出しではない呼び出しサイトの前に発行する必要があります。これはコンテキストプロファイリングで使用され、副作用があります。その低レベル化はIRで行われ、ターゲット固有のバックエンドはそれを認識すべきではありません。

引数:

最初の4つの引数は、llvm.instrprof.increment と同様です。インデックスは呼び出しサイトに固有のものであり、呼び出しサイトは0からインデックス付けされ、他の組み込み関数(llvm.instrprof.increment[.step] など)で使用されるインデックスとは独立しています。

最後の引数は、この組み込み関数が先行する呼び出しサイトの呼び出し値です。

セマンティクス:

これはコンテキストプロファイリングによって低レベル化されます。コンテキストプロファイリングでは、関数はコンパイラランタイムからコンテキストオブジェクトへのポインタを取得します。コンテキストオブジェクトは、LLVMがカウンタインクリメントを実行するために使用できるバッファ(つまり、llvm.instrprof.increment[.step] の低レベル化)で構成されています。カウンタバッファに続くアドレス範囲、<num-counters> x sizeof(ptr) のサイズの領域には、この関数から呼び出される関数のコンテキスト(「サブコンテキスト」)へのポインタが含まれていると想定されます。LLVMはそのメモリ領域を間接参照せず、GEPを計算するだけです。

llvm.instrprof.callsite の低レベル化は次のようになります。

  • __llvm_ctx_profile_expected_callee<callsite> 値を書き込む。

  • __llvm_ctx_profile_callsite に、サブコンテキスト領域の <index> 位置に対するこの関数のコンテキストのアドレスを書き込む。

__llvm_ctx_profile_{expected_callee|callsite} はコンパイラランタイムによって初期化され、TLSです。これらは両方ともサイズ2のポインタのベクトルです。各インデックスへのインデックスは、現在の関数がコンパイラランタイムからそのコンテキストへのポインタを取得するときに決定されます。ポインタのLSBがインデックスを与えます。

llvm.instrprof.timestamp’ 組み込み関数

構文:
declare void @llvm.instrprof.timestamp(i8* <name>, i64 <hash>,
                                       i32 <num-counters>, i32 <index>)
概要:

llvm.instrprof.timestamp’ 組み込み関数は、時間プロファイリングを実装するために使用されます。

引数:

引数は、 ‘llvm.instrprof.increment’ と同じです。index は常にゼロであることが期待されます。

セマンティクス:

llvm.instrprof.increment’ 組み込み関数に似ていますが、この関数が初めて実行されたときのタイムスタンプを格納します。

llvm.instrprof.cover’ 組み込み関数

構文:
declare void @llvm.instrprof.cover(ptr <name>, i64 <hash>,
                                   i32 <num-counters>, i32 <index>)
概要:

llvm.instrprof.cover’ 組み込み関数は、カバレッジ計測を実装するために使用されます。

引数:

引数は、 ‘llvm.instrprof.increment’ の最初の4つの引数と同じです。

セマンティクス:

llvm.instrprof.increment’ 組み込み関数に似ていますが、関数がカバーされたことを示すためにプロファイリング変数にゼロを格納します。一部のターゲットではこれがより効率的であるため、ゼロを格納します。

llvm.instrprof.value.profile’ 組み込み関数

構文:
declare void @llvm.instrprof.value.profile(ptr <name>, i64 <hash>,
                                           i64 <value>, i32 <value_kind>,
                                           i32 <index>)
概要:

llvm.instrprof.value.profile’ 組み込み関数は、フロントエンドによって、計測ベースのプロファイリングで使用するために発行できます。これは、-instrprof パスによって、ターゲット値を見つけ出すために低レベル化されます。計測された式は、実行時にプログラムに入力されます。

引数:

最初の引数は、計測対象のエンティティの名前を含むグローバル変数へのポインタです。name は、一般的にカウンタのセットのマングルされた関数名である必要があります。

2番目の引数は、プロファイルデータのコンシューマが、計測されたソースへの変更を検出するために使用できるハッシュ値です。llvm.instrprof.* の同じ名前を参照する2つのインスタンス間で hash が異なる場合はエラーです。

3番目の引数は、プロファイリングされる式の値です。プロファイリングされる式の値は、符号なし64ビット値として表現できる必要があります。4番目の引数は、実行されている値プロファイリングの種類を表します。サポートされている値プロファイリングの種類は、<include/llvm/ProfileData/InstrProf.h> ヘッダーファイルで宣言されている InstrProfValueKind 型によって列挙されます。最後の引数は、name 内の計測された式のインデックスです。これは >= 0 である必要があります。

セマンティクス:

この組み込み関数は、ターゲット式の値プロファイリングのためにランタイムルーチンへの呼び出しを挿入する必要がある場所を表します。-instrprof パスは、適切なデータ構造を生成し、llvm.instrprof.value.profile 組み込み関数を、適切な引数を持つプロファイルランタイムライブラリへの呼び出しに置き換えます。

llvm.instrprof.mcdc.parameters’ 組み込み関数

構文:
declare void @llvm.instrprof.mcdc.parameters(ptr <name>, i64 <hash>,
                                             i32 <bitmap-bits>)
概要:

llvm.instrprof.mcdc.parameters’ 組み込み関数は、関数のMC/DCコードカバレッジ計測を開始するために使用されます。

引数:

最初の引数は、インストルメント化されているエンティティの名前を含むグローバル変数へのポインタです。これは一般的に、カウンタセットのマングルされた関数名である必要があります。

2番目の引数は、プロファイルデータのコンシューマが、計測されたソースへの変更を検出するために使用できるハッシュ値です。

3番目の引数は、各ブール式の実行されたテストベクトルの数を記録するために関数に必要なビットマップビットの数です。

セマンティクス:

この組み込み関数は、関数内で1つ以上のMC/DC計測シーケンスを開始する基本的なMC/DCパラメータを表します。これにより、-instrprof パスは、適切なデータ構造と、コンパイラランタイムによって書き出され、llvm-profdata ツールを介して利用できる形式でMC/DCテストベクトルを計測するコードを生成します。

llvm.instrprof.mcdc.tvbitmap.update’ 組み込み関数

構文:
declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr <name>, i64 <hash>,
                                                  i32 <bitmap-index>,
                                                  ptr <mcdc-temp-addr>)
概要:

llvm.instrprof.mcdc.tvbitmap.update’ 組み込み関数は、各ブール式が完全に実行された後、MC/DCテストベクトルの実行を追跡するために使用されます。条件ビットマップの全体的な値は、各条件の真または偽の評価で連続して更新された後、実行されたMC/DCテストベクトルを一意に識別し、グローバルテストベクトルビットマップへのビットインデックスとして使用されます。

引数:

最初の引数は、インストルメント化されているエンティティの名前を含むグローバル変数へのポインタです。これは一般的に、カウンタセットのマングルされた関数名である必要があります。

2番目の引数は、プロファイルデータのコンシューマが、計測されたソースへの変更を検出するために使用できるハッシュ値です。

3番目の引数は、関数に対応するグローバルテストベクトルビットマップへのビットインデックスです。

4番目の引数は、実行されたMC/DCテストベクトルを表す値を含む条件ビットマップのアドレスです。これはロードされ、テストベクトルビットマップのビットインデックスとして使用されます。

セマンティクス:

この組み込み関数は、MC/DC計測シーケンスの最後の操作を表し、-instrprof パスは、テストベクトルが実行されたことを示すために、関数のグローバルテストベクトルビットマップの更新を計測するコードを生成します。グローバルテストベクトルビットマップは、llvm-profdata および llvm-cov ツールで使用できます。

llvm.thread.pointer’ 組み込み関数

構文:
declare ptr @llvm.thread.pointer()
概要:

llvm.thread.pointer’ 組み込み関数は、スレッドポインタの値を返します。

セマンティクス:

llvm.thread.pointer’ 組み込み関数は、現在のスレッドの TLS 領域へのポインタを返します。この値の正確なセマンティクスはターゲット固有です。TLS 領域の開始点、終了点、または中間のどこかを指す場合があります。ターゲットによっては、この組み込み関数はレジスタを読み取ったり、ヘルパー関数を呼び出したり、別のメモリ空間から読み取ったり、TLS 領域を見つけるために必要なその他の操作を実行したりする場合があります。すべてのターゲットがこの組み込み関数をサポートしているわけではありません。

llvm.call.preallocated.setup’ 組み込み関数

構文:
declare token @llvm.call.preallocated.setup(i32 %num_args)
概要:

llvm.call.preallocated.setup’ 組み込み関数は、特定の引数が呼び出し前に割り当てられ初期化されていることを示すために、呼び出しの "preallocated" オペランドバンドルで使用できるトークンを返します。

セマンティクス:

llvm.call.preallocated.setup’ 組み込み関数は、最大で 1 つの呼び出しに関連付けられたトークンを返します。このトークンは、対応する引数へのポインタを取得するために ‘@llvm.call.preallocated.arg’ に渡すことができます。トークンは、対応する呼び出しの "preallocated" オペランドバンドルのパラメータである必要があります。

llvm.call.preallocated.setup’ のネストされた呼び出しは許可されますが、正しくネストされている必要があります。例:

:: code-block:: llvm

%t1 = call token @llvm.call.preallocated.setup(i32 0) %t2 = call token @llvm.call.preallocated.setup(i32 0) call void foo() [“preallocated”(token %t2)] call void foo() [“preallocated”(token %t1)]

は許可されていますが、以下は許可されていません。

:: code-block:: llvm

%t1 = call token @llvm.call.preallocated.setup(i32 0) %t2 = call token @llvm.call.preallocated.setup(i32 0) call void foo() [“preallocated”(token %t1)] call void foo() [“preallocated”(token %t2)]

llvm.call.preallocated.arg’ 組み込み関数

構文:
declare ptr @llvm.call.preallocated.arg(token %setup_token, i32 %arg_index)
概要:

llvm.call.preallocated.arg’ 組み込み関数は、プリアロケートされた呼び出しの、対応するプリアロケートされた引数へのポインタを返します。

セマンティクス:

llvm.call.preallocated.arg’ 組み込み関数は、 ‘%setup_token’ に関連付けられた呼び出しの、%arg_index 番目の、preallocated 属性を持つ引数へのポインタを返します。これは ‘llvm.call.preallocated.setup’ からのものである必要があります。

llvm.call.preallocated.arg’ の呼び出しには、呼び出しサイトに preallocated 属性が必要です。 preallocated 属性の型は、プリアロケートされた呼び出しの対応する引数で使用されている型と一致する必要があります。この型は、llvm.call.preallocated.setup に対応する呼び出しがない場合 (例えば、DCE による) に使用されます。そうでないと、引数の大きさを知ることができないためです。

別の ‘llvm.call.preallocated.setup’ が既に呼び出されている場合、または ‘llvm.call.preallocated.setup’ に対応するプリアロケートされた呼び出しが既に呼び出されている場合に、 ‘llvm.call.preallocated.setup’ からのトークンでこれを呼び出すと、未定義の動作になります。

llvm.call.preallocated.teardown’ 組み込み関数

構文:
declare ptr @llvm.call.preallocated.teardown(token %setup_token)
概要:

llvm.call.preallocated.teardown’ 組み込み関数は、 ‘llvm.call.preallocated.setup’ によって作成されたスタックをクリーンアップします。

セマンティクス:

トークン引数は ‘llvm.call.preallocated.setup’ である必要があります。

llvm.call.preallocated.teardown’ 組み込み関数は、対応する ‘llvm.call.preallocated.setup’ によって割り当てられたスタックをクリーンアップします。スタックリークを防ぐために、この関数またはプリアロケートされた呼び出しのどちらか一方のみを呼び出す必要があります。特定の ‘llvm.call.preallocated.setup’ に対して、 ‘llvm.call.preallocated.teardown’ とプリアロケートされた呼び出しの両方を呼び出すと、未定義の動作になります。

たとえば、 ‘llvm.call.preallocated.setup’ によってプリアロケートされた呼び出しのためにスタックが割り当てられ、割り当てられた引数で呼び出された初期化関数が例外をスローした場合、スタックリークを防ぐために例外ハンドラーに ‘llvm.call.preallocated.teardown’ がある必要があります。

llvm.call.preallocated.setup’ のネスト規則に従い、 ‘llvm.call.preallocated.setup’ と ‘llvm.call.preallocated.teardown’ のネストされた呼び出しは許可されますが、正しくネストされている必要があります。

例:
    %cs = call token @llvm.call.preallocated.setup(i32 1)
    %x = call ptr @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
    invoke void @constructor(ptr %x) to label %conta unwind label %contb
conta:
    call void @foo1(ptr preallocated(i32) %x) ["preallocated"(token %cs)]
    ret void
contb:
    %s = catchswitch within none [label %catch] unwind to caller
catch:
    %p = catchpad within %s []
    call void @llvm.call.preallocated.teardown(token %cs)
    ret void

標準 C/C++ ライブラリ組み込み関数

LLVM は、いくつかの重要な標準 C/C++ ライブラリ関数に対して組み込み関数を提供します。これらの組み込み関数により、ソース言語のフロントエンドは、ポインタ引数のアライメントに関する情報をコードジェネレータに渡すことができ、より効率的なコード生成の機会を提供できます。

llvm.abs.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数要素の任意のベクトルの llvm.abs を使用できます。

declare i32 @llvm.abs.i32(i32 <src>, i1 <is_int_min_poison>)
declare <4 x i32> @llvm.abs.v4i32(<4 x i32> <src>, i1 <is_int_min_poison>)
概要:

llvm.abs’ ファミリーの組み込み関数は、引数の絶対値を返します。

引数:

最初の引数は、絶対値が返される値です。この引数は、任意の整数型または整数要素型を持つベクトルにすることができます。戻り値の型は、最初の引数の型と一致する必要があります。

2 番目の引数は定数でなければならず、最初の引数が静的または動的に INT_MIN 値である場合に、 ‘llvm.abs’ 組み込み関数の結果値が poison value であるかどうかを示すフラグです。

セマンティクス:

llvm.abs’ 組み込み関数は、最初の引数またはベクトル引数の各要素の大きさ (常に正) を返します。最初の引数が INT_MIN の場合、 is_int_min_poison == 0 であれば結果も INT_MIN であり、それ以外の場合は poison です。

llvm.smax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数要素の任意のベクトルの @llvm.smax を使用できます。

declare i32 @llvm.smax.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b のうち、符号付き整数として比較して大きい方を返します。ベクトル組み込み関数は、要素ごとに動作します。指定されたインデックスで %a%b のうち、大きい方の要素がそのインデックスに対して返されます。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクトルにすることができます。引数の型は互いに一致する必要があり、戻り値の型は引数の型と一致する必要があります。

llvm.smin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数要素の任意のベクトルの @llvm.smin を使用できます。

declare i32 @llvm.smin.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.smin.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b のうち、符号付き整数として比較して小さい方を返します。ベクター組み込み関数は要素ごとに動作します。指定されたインデックスにおいて、%a%b の小さい方の要素がそのインデックスに対して返されます。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクトルにすることができます。引数の型は互いに一致する必要があり、戻り値の型は引数の型と一致する必要があります。

llvm.umax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。@llvm.umax は、任意の整数ビット幅または整数要素の任意のベクターで使用できます。

declare i32 @llvm.umax.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b のうち、符号なし整数として比較して大きい方を返します。ベクター組み込み関数は要素ごとに動作します。指定されたインデックスにおいて、%a%b の大きい方の要素がそのインデックスに対して返されます。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクトルにすることができます。引数の型は互いに一致する必要があり、戻り値の型は引数の型と一致する必要があります。

llvm.umin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。@llvm.umin は、任意の整数ビット幅または整数要素の任意のベクターで使用できます。

declare i32 @llvm.umin.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.umin.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b のうち、符号なし整数として比較して小さい方を返します。ベクター組み込み関数は要素ごとに動作します。指定されたインデックスにおいて、%a%b の小さい方の要素がそのインデックスに対して返されます。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクトルにすることができます。引数の型は互いに一致する必要があり、戻り値の型は引数の型と一致する必要があります。

llvm.scmp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。@llvm.scmp は、任意の整数ビット幅または整数要素の任意のベクターで使用できます。

declare i2 @llvm.scmp.i2.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b より符号付きで小さい場合は -1、等しい場合は 0%a%b より符号付きで大きい場合は 1 を返します。ベクター組み込み関数は要素ごとに動作します。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクターにすることができます。引数型は互いに一致する必要があり、戻り値型は、可能な3つの戻り値を保持するために、少なくとも i2 の幅が必要です。

llvm.ucmp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。@llvm.ucmp は、任意の整数ビット幅または整数要素の任意のベクターで使用できます。

declare i2 @llvm.ucmp.i2.i32(i32 %a, i32 %b)
declare <4 x i32> @llvm.ucmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

%a%b より符号なしで小さい場合は -1、等しい場合は 0%a%b より符号なしで大きい場合は 1 を返します。ベクター組み込み関数は要素ごとに動作します。

引数:

引数 (%a%b) は、任意の整数型または整数要素型を持つベクターにすることができます。引数型は互いに一致する必要があり、戻り値型は、可能な3つの戻り値を保持するために、少なくとも i2 の幅が必要です。

llvm.memcpy’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.memcpy は、任意の整数ビット幅と異なるアドレス空間で使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memcpy.p0.p0.i32(ptr <dest>, ptr <src>,
                                    i32 <len>, i1 <isvolatile>)
declare void @llvm.memcpy.p0.p0.i64(ptr <dest>, ptr <src>,
                                    i64 <len>, i1 <isvolatile>)
概要:

llvm.memcpy.*’ 組み込み関数は、ソースロケーションからデスティネーションロケーションにメモリのブロックをコピーします。

標準の libc 関数とは異なり、llvm.memcpy.* 組み込み関数は値を返さず、追加の isvolatile 引数をとり、ポインターは指定されたアドレス空間に存在できることに注意してください。

引数:

最初の引数はデスティネーションへのポインター、2番目の引数はソースへのポインターです。3番目の引数はコピーするバイト数を指定する整数引数であり、4番目の引数は揮発性アクセスを示すブール値です。

align パラメーター属性を最初と2番目の引数に指定できます。

isvolatile パラメーターが true の場合、llvm.memcpy 呼び出しは 揮発性操作 です。詳細なアクセス動作はあまり明確に指定されておらず、それに依存することは賢明ではありません。

セマンティクス:

llvm.memcpy.*’ 組み込み関数は、ソースロケーションからデスティネーションロケーションにメモリのブロックをコピーします。これは、等しいか、重複していないかのいずれかである必要があります。「len」バイトのメモリをコピーします。引数が特定のアラインメント境界にアラインされていることがわかっている場合は、引数の属性として指定できます。

<len> が 0 の場合、引数に付加された属性の動作を法として、ノーオペレーションになります。<len> が適切に定義された値でない場合、動作は未定義です。<len> がゼロでない場合、<dest><src> の両方が適切に定義されている必要があります。そうでない場合、動作は未定義です。

llvm.memcpy.inline’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.memcpy.inline は、任意の整数ビット幅と異なるアドレス空間で使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memcpy.inline.p0.p0.i32(ptr <dest>, ptr <src>,
                                           i32 <len>, i1 <isvolatile>)
declare void @llvm.memcpy.inline.p0.p0.i64(ptr <dest>, ptr <src>,
                                           i64 <len>, i1 <isvolatile>)
概要:

llvm.memcpy.inline.*’ 組み込み関数は、ソースロケーションからデスティネーションロケーションにメモリのブロックをコピーし、外部関数が呼び出されないことを保証します。

標準の libc 関数とは異なり、llvm.memcpy.inline.* 組み込み関数は値を返さず、追加の isvolatile 引数をとり、ポインターは指定されたアドレス空間に存在できることに注意してください。

引数:

最初の引数はデスティネーションへのポインター、2番目の引数はソースへのポインターです。3番目の引数はコピーするバイト数を指定する整数引数であり、4番目の引数は揮発性アクセスを示すブール値です。

align パラメーター属性を最初と2番目の引数に指定できます。

isvolatile パラメーターが true の場合、llvm.memcpy.inline 呼び出しは 揮発性操作 です。詳細なアクセス動作はあまり明確に指定されておらず、それに依存することは賢明ではありません。

セマンティクス:

llvm.memcpy.inline.*’ 組み込み関数は、ソースロケーションからデスティネーションロケーションにメモリのブロックをコピーします。これらのロケーションは重複することはできません。「len」バイトのメモリをコピーします。引数が特定のアラインメント境界にアラインされていることがわかっている場合は、引数の属性として指定できます。‘llvm.memcpy.inline.*’ の動作は ‘llvm.memcpy.*’ の動作と同等ですが、生成されたコードは外部関数を呼び出さないことが保証されています。

llvm.memmove’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.memmove は、任意の整数ビット幅と異なるアドレス空間で使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memmove.p0.p0.i32(ptr <dest>, ptr <src>,
                                     i32 <len>, i1 <isvolatile>)
declare void @llvm.memmove.p0.p0.i64(ptr <dest>, ptr <src>,
                                     i64 <len>, i1 <isvolatile>)
概要:

llvm.memmove.*’ 組み込み関数は、ソースロケーションからデスティネーションロケーションにメモリのブロックを移動します。これは ‘llvm.memcpy’ 組み込み関数に似ていますが、2つのメモリロケーションが重複することを許可します。

標準の libc 関数とは異なり、llvm.memmove.* 組み込み関数は値を返さず、追加の isvolatile 引数をとり、ポインターは指定されたアドレス空間に存在できることに注意してください。

引数:

最初の引数はデスティネーションへのポインター、2番目の引数はソースへのポインターです。3番目の引数はコピーするバイト数を指定する整数引数であり、4番目の引数は揮発性アクセスを示すブール値です。

align パラメーター属性を最初と2番目の引数に指定できます。

isvolatile パラメータが true の場合、llvm.memmove 呼び出しは揮発性操作になります。詳細なアクセス動作は明確に規定されておらず、それに依存することは賢明ではありません。

セマンティクス:

llvm.memmove.*」組み込み関数は、ソースロケーションからデスティネーションロケーションへメモリブロックをコピーします。これらは重複する可能性があります。「len」バイトのメモリがコピーされます。引数が特定の境界にアラインされていることがわかっている場合、これは引数の属性として指定できます。

<len> が 0 の場合、引数に付加された属性の動作を法として、ノーオペレーションになります。<len> が適切に定義された値でない場合、動作は未定義です。<len> がゼロでない場合、<dest><src> の両方が適切に定義されている必要があります。そうでない場合、動作は未定義です。

llvm.memset.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅と異なるアドレス空間に対して llvm.memset を使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memset.p0.i32(ptr <dest>, i8 <val>,
                                 i32 <len>, i1 <isvolatile>)
declare void @llvm.memset.p0.i64(ptr <dest>, i8 <val>,
                                 i64 <len>, i1 <isvolatile>)
概要:

llvm.memset.*」組み込み関数は、メモリブロックを特定のバイト値で埋めます。

標準の libc 関数とは異なり、llvm.memset 組み込み関数は値を返さず、追加の volatile 引数を取ることに注意してください。また、デスティネーションは任意のアドレス空間に配置できます。

引数:

最初の引数は、埋めるデスティネーションへのポインタ、2番目の引数は埋めるバイト値、3番目の引数は埋めるバイト数を指定する整数引数、4番目の引数は揮発性アクセスを示すブール値です。

align パラメータ属性は、最初の引数に指定できます。

isvolatile パラメータが true の場合、llvm.memset 呼び出しは揮発性操作になります。詳細なアクセス動作は明確に規定されておらず、それに依存することは賢明ではありません。

セマンティクス:

llvm.memset.*」組み込み関数は、デスティネーションロケーションから始まる「len」バイトのメモリを埋めます。引数が特定の境界にアラインされていることがわかっている場合、これは引数の属性として指定できます。

<len> が 0 の場合、引数に付与された属性の動作を除き、no-op になります。<len> が明確に定義された値でない場合、動作は未定義です。<len> が 0 でない場合、<dest> は明確に定義されている必要があります。そうでない場合、動作は未定義です。

llvm.memset.inline」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅と異なるアドレス空間に対して llvm.memset.inline を使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memset.inline.p0.p0i8.i32(ptr <dest>, i8 <val>,
                                             i32 <len>, i1 <isvolatile>)
declare void @llvm.memset.inline.p0.p0.i64(ptr <dest>, i8 <val>,
                                           i64 <len>, i1 <isvolatile>)
概要:

llvm.memset.inline.*」組み込み関数は、メモリブロックを特定のバイト値で埋め、外部関数が呼び出されないことを保証します。

標準の libc 関数とは異なり、llvm.memset.inline.* 組み込み関数は値を返さず、追加の isvolatile 引数を取り、ポインタは指定されたアドレス空間に配置できます。

引数:

最初の引数は、埋めるデスティネーションへのポインタ、2番目の引数は埋めるバイト値、3番目の引数は埋めるバイト数を指定する定数整数引数、4番目の引数は揮発性アクセスを示すブール値です。

align パラメータ属性は、最初の引数に指定できます。

isvolatile パラメータが true の場合、llvm.memset.inline 呼び出しは揮発性操作になります。詳細なアクセス動作は明確に規定されておらず、それに依存することは賢明ではありません。

セマンティクス:

llvm.memset.inline.*」組み込み関数は、デスティネーションロケーションから始まる「len」バイトのメモリを埋めます。引数が特定の境界にアラインされていることがわかっている場合、これは引数の属性として指定できます。

<len> が 0 の場合、引数に付与された属性の動作を除き、no-op になります。<len> が明確に定義された値でない場合、動作は未定義です。<len> が 0 でない場合、<dest> は明確に定義されている必要があります。そうでない場合、動作は未定義です。

llvm.memset.inline.*」の動作は、「llvm.memset.*」の動作と同等ですが、生成されたコードは外部関数を呼び出さないことが保証されています。

llvm.sqrt.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.sqrt を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.sqrt.f32(float %Val)
declare double    @llvm.sqrt.f64(double %Val)
declare x86_fp80  @llvm.sqrt.f80(x86_fp80 %Val)
declare fp128     @llvm.sqrt.f128(fp128 %Val)
declare ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %Val)
概要:

llvm.sqrt」組み込み関数は、指定された値の平方根を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の「sqrt」関数と同じ値を返しますが、トラップや errno の設定は行いません。IEEE-754 で指定された型の場合、結果は準拠する libm 実装と一致します。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.powi.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.powi を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

一般に、指数にサポートされる唯一の型は、C 型 int に一致する型です。

declare float     @llvm.powi.f32.i32(float  %Val, i32 %power)
declare double    @llvm.powi.f64.i16(double %Val, i16 %power)
declare x86_fp80  @llvm.powi.f80.i32(x86_fp80  %Val, i32 %power)
declare fp128     @llvm.powi.f128.i32(fp128 %Val, i32 %power)
declare ppc_fp128 @llvm.powi.ppcf128.i32(ppc_fp128  %Val, i32 %power)
概要:

llvm.powi.*」組み込み関数は、最初のオペランドを指定された(正または負の)累乗で累乗した値を返します。乗算の評価順序は定義されていません。浮動小数点型のベクトルが使用されている場合、2番目の引数はスカラー整数値のままです。

引数:

2番目の引数は整数の累乗であり、最初の引数はその累乗にする値です。

セマンティクス:

この関数は、丸め演算の順序が指定されていない状態で、最初の値を2番目の累乗で累乗した値を返します。

llvm.sin.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.sin を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.sin.f32(float  %Val)
declare double    @llvm.sin.f64(double %Val)
declare x86_fp80  @llvm.sin.f80(x86_fp80  %Val)
declare fp128     @llvm.sin.f128(fp128 %Val)
declare ppc_fp128 @llvm.sin.ppcf128(ppc_fp128  %Val)
概要:

llvm.sin.*」組み込み関数は、オペランドの正弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の「sin」関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.cos.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.cos を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.cos.f32(float  %Val)
declare double    @llvm.cos.f64(double %Val)
declare x86_fp80  @llvm.cos.f80(x86_fp80  %Val)
declare fp128     @llvm.cos.f128(fp128 %Val)
declare ppc_fp128 @llvm.cos.ppcf128(ppc_fp128  %Val)
概要:

llvm.cos.*」組み込み関数は、オペランドの余弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の「cos」関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.tan.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.tan を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.tan.f32(float  %Val)
declare double    @llvm.tan.f64(double %Val)
declare x86_fp80  @llvm.tan.f80(x86_fp80  %Val)
declare fp128     @llvm.tan.f128(fp128 %Val)
declare ppc_fp128 @llvm.tan.ppcf128(ppc_fp128  %Val)
概要:

llvm.tan.*’ 組み込み関数は、オペランドの正接を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘tan’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.asin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.asin は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.asin.f32(float  %Val)
declare double    @llvm.asin.f64(double %Val)
declare x86_fp80  @llvm.asin.f80(x86_fp80  %Val)
declare fp128     @llvm.asin.f128(fp128 %Val)
declare ppc_fp128 @llvm.asin.ppcf128(ppc_fp128  %Val)
概要:

llvm.asin.*’ 組み込み関数は、オペランドの逆正弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘asin’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.acos.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.acos は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.acos.f32(float  %Val)
declare double    @llvm.acos.f64(double %Val)
declare x86_fp80  @llvm.acos.f80(x86_fp80  %Val)
declare fp128     @llvm.acos.f128(fp128 %Val)
declare ppc_fp128 @llvm.acos.ppcf128(ppc_fp128  %Val)
概要:

llvm.acos.*’ 組み込み関数は、オペランドの逆余弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘acos’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.atan.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.atan は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.atan.f32(float  %Val)
declare double    @llvm.atan.f64(double %Val)
declare x86_fp80  @llvm.atan.f80(x86_fp80  %Val)
declare fp128     @llvm.atan.f128(fp128 %Val)
declare ppc_fp128 @llvm.atan.ppcf128(ppc_fp128  %Val)
概要:

llvm.atan.*’ 組み込み関数は、オペランドの逆正接を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘atan’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.sinh.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.sinh は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.sinh.f32(float  %Val)
declare double    @llvm.sinh.f64(double %Val)
declare x86_fp80  @llvm.sinh.f80(x86_fp80  %Val)
declare fp128     @llvm.sinh.f128(fp128 %Val)
declare ppc_fp128 @llvm.sinh.ppcf128(ppc_fp128  %Val)
概要:

llvm.sinh.*’ 組み込み関数は、オペランドの双曲線正弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘sinh’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.cosh.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.cosh は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.cosh.f32(float  %Val)
declare double    @llvm.cosh.f64(double %Val)
declare x86_fp80  @llvm.cosh.f80(x86_fp80  %Val)
declare fp128     @llvm.cosh.f128(fp128 %Val)
declare ppc_fp128 @llvm.cosh.ppcf128(ppc_fp128  %Val)
概要:

llvm.cosh.*’ 組み込み関数は、オペランドの双曲線余弦を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘cosh’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.tanh.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.tanh は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.tanh.f32(float  %Val)
declare double    @llvm.tanh.f64(double %Val)
declare x86_fp80  @llvm.tanh.f80(x86_fp80  %Val)
declare fp128     @llvm.tanh.f128(fp128 %Val)
declare ppc_fp128 @llvm.tanh.ppcf128(ppc_fp128  %Val)
概要:

llvm.tanh.*’ 組み込み関数は、オペランドの双曲線正接を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘tanh’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.pow.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.pow は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.pow.f32(float  %Val, float %Power)
declare double    @llvm.pow.f64(double %Val, double %Power)
declare x86_fp80  @llvm.pow.f80(x86_fp80  %Val, x86_fp80 %Power)
declare fp128     @llvm.pow.f128(fp128 %Val, fp128 %Power)
declare ppc_fp128 @llvm.pow.ppcf128(ppc_fp128  %Val, ppc_fp128 Power)
概要:

llvm.pow.*’ 組み込み関数は、最初のオペランドを指定された (正または負の) べき乗で累乗した値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘pow’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.exp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.exp は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.exp.f32(float  %Val)
declare double    @llvm.exp.f64(double %Val)
declare x86_fp80  @llvm.exp.f80(x86_fp80  %Val)
declare fp128     @llvm.exp.f128(fp128 %Val)
declare ppc_fp128 @llvm.exp.ppcf128(ppc_fp128  %Val)
概要:

llvm.exp.*’ 組み込み関数は、指定された値の自然指数 (e を底とする指数) を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘exp’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.exp2.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.exp2 は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.exp2.f32(float  %Val)
declare double    @llvm.exp2.f64(double %Val)
declare x86_fp80  @llvm.exp2.f80(x86_fp80  %Val)
declare fp128     @llvm.exp2.f128(fp128 %Val)
declare ppc_fp128 @llvm.exp2.ppcf128(ppc_fp128  %Val)
概要:

llvm.exp2.*’ 組み込み関数は、指定された値の 2 を底とする指数を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘exp2’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.exp10.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.exp10 は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.exp10.f32(float  %Val)
declare double    @llvm.exp10.f64(double %Val)
declare x86_fp80  @llvm.exp10.f80(x86_fp80  %Val)
declare fp128     @llvm.exp10.f128(fp128 %Val)
declare ppc_fp128 @llvm.exp10.ppcf128(ppc_fp128  %Val)
概要:

llvm.exp10.*’ 組み込み関数は、指定された値の 10 を底とする指数を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応する libm の ‘exp10’ 関数と同じ値を返しますが、トラップや errno の設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.ldexp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.ldexp は、任意の浮動小数点型または浮動小数点型のベクトルで使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.ldexp.f32.i32(float %Val, i32 %Exp)
declare double    @llvm.ldexp.f64.i32(double %Val, i32 %Exp)
declare x86_fp80  @llvm.ldexp.f80.i32(x86_fp80 %Val, i32 %Exp)
declare fp128     @llvm.ldexp.f128.i32(fp128 %Val, i32 %Exp)
declare ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 %Val, i32 %Exp)
declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %Val, <2 x i32> %Exp)
概要:

llvm.ldexp.*’ 組み込み関数は、ldexp 関数を実行します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数または浮動小数点数のベクトルです。2番目の引数は、要素数が同じ整数です。

セマンティクス:

この関数は、最初の引数に2のべき乗(2番目の引数)を掛けます。最初の引数がNaNまたは無限大の場合、同じ値が返されます。結果がアンダーフローする場合は、同じ符号のゼロが返されます。結果がオーバーフローする場合は、同じ符号の無限大が結果になります。

llvm.frexp.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.frexpは、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare { float, i32 }     @llvm.frexp.f32.i32(float %Val)
declare { double, i32 }    @llvm.frexp.f64.i32(double %Val)
declare { x86_fp80, i32 }  @llvm.frexp.f80.i32(x86_fp80 %Val)
declare { fp128, i32 }     @llvm.frexp.f128.i32(fp128 %Val)
declare { ppc_fp128, i32 } @llvm.frexp.ppcf128.i32(ppc_fp128 %Val)
declare { <2 x float>, <2 x i32> }  @llvm.frexp.v2f32.v2i32(<2 x float> %Val)
概要:

llvm.frexp.*」組み込み関数は、frexp関数を実行します。

引数:

引数は、浮動小数点数または浮動小数点数のベクトルです。構造体で2つの値を返します。最初の構造体フィールドは引数の型と一致し、2番目のフィールドは整数または引数と同じ数の要素を持つ整数のベクトルです。

セマンティクス:

この組み込み関数は、浮動小数点値を正規化された小数部成分と整数指数に分割します。

ゼロ以外の引数の場合、引数に2のべき乗を掛けた値を返し、返される値の絶対値が[0.5, 1.0)の範囲になるようにします。この値は引数と同じ符号を持ちます。2番目の結果は、最初の結果を2番目の結果のべき乗としたものが入力引数になるような整数です。

引数がゼロの場合、同じ符号のゼロと0の指数を返します。

引数がNaNの場合、NaNが返され、返される指数は未指定です。

引数が無限大の場合、同じ符号の無限大と未指定の指数が返されます。

llvm.log.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.logは、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.log.f32(float  %Val)
declare double    @llvm.log.f64(double %Val)
declare x86_fp80  @llvm.log.f80(x86_fp80  %Val)
declare fp128     @llvm.log.f128(fp128 %Val)
declare ppc_fp128 @llvm.log.ppcf128(ppc_fp128  %Val)
概要:

llvm.log.*」組み込み関数は、指定された値の自然対数を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応するlibmの「log」関数と同じ値を返しますが、トラップやerrnoの設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.log10.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.log10は、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.log10.f32(float  %Val)
declare double    @llvm.log10.f64(double %Val)
declare x86_fp80  @llvm.log10.f80(x86_fp80  %Val)
declare fp128     @llvm.log10.f128(fp128 %Val)
declare ppc_fp128 @llvm.log10.ppcf128(ppc_fp128  %Val)
概要:

llvm.log10.*」組み込み関数は、指定された値の常用対数を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応するlibmの「log10」関数と同じ値を返しますが、トラップやerrnoの設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.log2.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.log2は、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.log2.f32(float  %Val)
declare double    @llvm.log2.f64(double %Val)
declare x86_fp80  @llvm.log2.f80(x86_fp80  %Val)
declare fp128     @llvm.log2.f128(fp128 %Val)
declare ppc_fp128 @llvm.log2.ppcf128(ppc_fp128  %Val)
概要:

llvm.log2.*」組み込み関数は、指定された値の底が2の対数を計算します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

対応するlibmの「log2」関数と同じ値を返しますが、トラップやerrnoの設定は行いません。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.fma.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.fmaは、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.fma.f32(float  %a, float  %b, float  %c)
declare double    @llvm.fma.f64(double %a, double %b, double %c)
declare x86_fp80  @llvm.fma.f80(x86_fp80 %a, x86_fp80 %b, x86_fp80 %c)
declare fp128     @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c)
declare ppc_fp128 @llvm.fma.ppcf128(ppc_fp128 %a, ppc_fp128 %b, ppc_fp128 %c)
概要:

llvm.fma.*」組み込み関数は、融合乗算加算演算を実行します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

IEEE-754の融合乗算加算演算と同じ値を返します。これはトラップやerrnoの設定を行わないと想定されます。

高速数学フラグ「afn」を指定すると、精度が低い計算で結果が近似される場合があります。

llvm.fabs.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.fabsは、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.fabs.f32(float  %Val)
declare double    @llvm.fabs.f64(double %Val)
declare x86_fp80  @llvm.fabs.f80(x86_fp80 %Val)
declare fp128     @llvm.fabs.f128(fp128 %Val)
declare ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 %Val)
概要:

llvm.fabs.*」組み込み関数は、オペランドの絶対値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libmのfabs関数と同じ値を返し、エラー状態も同様に処理します。返される値は符号ビットを除いて入力と完全に同じです。特に、入力がNaNの場合、quiet/signalingビットとペイロードは完全に保持されます。

llvm.min.*」組み込み関数の比較

標準:

IEEE754とISO Cはいくつかのmin/max演算を定義していますが、qNaN/sNaNと+0.0/-0.0の扱いにはいくつかの違いがあります。以下にリストを示します。

ISO C

fmin/fmax

fmininum/fmaximum

fminimum_num/fmaximum_num

IEEE754

minNum/maxNum (2008)

minimum/maximum (2019)

minimumNumber/maximumNumber (2019)

+0.0 -0.0

どちらか一方

+0.0 > -0.0

+0.0 > -0.0

NUM sNaN

qNaN、無効例外

qNaN、無効例外

NUM、無効例外

qNaN sNaN

qNaN、無効例外

qNaN、無効例外

qNaN、無効例外

NUM qNaN

NUM、例外なし

qNaN、例外なし

NUM、例外なし

LLVM実装:

LLVMは、この表にリストされているすべてのISO Cフレーバーを実装していますが、デフォルトの浮動小数点環境では例外は無視されます。組み込み関数の制約付きバージョンは、例外の動作を尊重します。

操作

minnum/maxnum

minimum/maximum

minimumnum/maximumnum

NUM qNaN

NUM、例外なし

qNaN、例外なし

NUM、例外なし

NUM sNaN

qNaN、無効例外

qNaN、無効例外

NUM、無効例外

qNaN sNaN

qNaN、無効例外

qNaN、無効例外

qNaN、無効例外

sNaN sNaN

qNaN、無効例外

qNaN、無効例外

qNaN、無効例外

+0.0 -0.0

どちらか一方

+0.0(max)/-0.0(min)

+0.0(max)/-0.0(min)

NUM NUM

大きい方(max)/小さい方(min)

大きい方(max)/小さい方(min)

大きい方(max)/小さい方(min)

llvm.minnum.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.minnumは、任意の浮動小数点型または浮動小数点型のベクトルに使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.minnum.f32(float %Val0, float %Val1)
declare double    @llvm.minnum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.minnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
declare fp128     @llvm.minnum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
概要:

llvm.minnum.*」組み込み関数は、2つの引数の最小値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

シグナリングNaNの処理を除き、minNumのIEEE-754セマンティクスに従います。これは、libmのfminの動作と一致します。

どちらかのオペランドがNaNの場合、他の非NaNオペランドを返します。両方のオペランドがNaNの場合にのみNaNを返します。オペランドが等しい場合、どちらかのオペランドを返します。たとえば、これはfmin(+0.0, -0.0)がいずれかのオペランドを返すことを意味します。

IEEE-754 2008の動作とは異なり、シグナリングNaNとquiet NaN入力を区別しません。ターゲットの実装が標準に従い、いずれかの入力がシグナリングNaNの場合にquiet NaNを返す場合、組み込み関数の低レベル化は、非NaN入力を正しく返すために入力をquietにする責任があります(例えば、llvm.canonicalizeと同等のものを使用するなど)。

llvm.maxnum.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.maxnum を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.maxnum.f32(float  %Val0, float  %Val1)
declare double    @llvm.maxnum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.maxnum.f80(x86_fp80  %Val0, x86_fp80  %Val1)
declare fp128     @llvm.maxnum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128  %Val0, ppc_fp128  %Val1)
概要:

llvm.maxnum.*’ 組み込み関数は、2つの引数のうち大きい方を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

シグナリング NaN の処理を除き、maxNum の IEEE-754 セマンティクスに従います。これは libm の fmax の動作と一致します。

オペランドのいずれかが NaN の場合、NaN でない方のオペランドを返します。両方のオペランドが NaN の場合にのみ NaN を返します。オペランドが等しい場合、いずれかのオペランドを返します。たとえば、これは fmax(+0.0, -0.0) が -0.0 または 0.0 のいずれかを返すことを意味します。

IEEE-754 2008の動作とは異なり、シグナリングNaNとquiet NaN入力を区別しません。ターゲットの実装が標準に従い、いずれかの入力がシグナリングNaNの場合にquiet NaNを返す場合、組み込み関数の低レベル化は、非NaN入力を正しく返すために入力をquietにする責任があります(例えば、llvm.canonicalizeと同等のものを使用するなど)。

llvm.minimum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.minimum を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.minimum.f32(float %Val0, float %Val1)
declare double    @llvm.minimum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.minimum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
declare fp128     @llvm.minimum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.minimum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
概要:

llvm.minimum.*’ 組み込み関数は、2つの引数のうち小さい方を返し、NaN を伝播し、-0.0 を +0.0 より小さいものとして扱います。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

オペランドのいずれかが NaN の場合、NaN を返します。それ以外の場合は、2つの引数のうち小さい方を返します。この組み込み関数では、-0.0 は +0.0 より小さいと見なされます。これらは IEEE 754-2019 のドラフトで指定されたセマンティクスであることに注意してください。

llvm.maximum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.maximum を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.maximum.f32(float %Val0, float %Val1)
declare double    @llvm.maximum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.maximum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
declare fp128     @llvm.maximum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.maximum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
概要:

llvm.maximum.*’ 組み込み関数は、2つの引数のうち大きい方を返し、NaN を伝播し、-0.0 を +0.0 より小さいものとして扱います。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

オペランドのいずれかが NaN の場合、NaN を返します。それ以外の場合は、2つの引数のうち大きい方を返します。この組み込み関数では、-0.0 は +0.0 より小さいと見なされます。これらは IEEE 754-2019 のドラフトで指定されたセマンティクスであることに注意してください。

llvm.minimumnum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.minimumnum を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.minimumnum.f32(float %Val0, float %Val1)
declare double    @llvm.minimumnum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.minimumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
declare fp128     @llvm.minimumnum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.minimumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
概要:

llvm.minimumnum.*’ 組み込み関数は、2つの引数のうち小さい方を返し、NaN を伝播せず、-0.0 を +0.0 より小さいものとして扱います。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

両方のオペランドが NaN (sNaN を含む) の場合、qNaN を返します。一方のオペランドが NaN (sNaN を含む) で、もう一方のオペランドが数値の場合、その数値を返します。それ以外の場合は、2つの引数のうち小さい方を返します。この組み込み関数では、-0.0 は +0.0 より小さいと見なされます。

これらは IEEE 754-2019 で指定された minimumNumber のセマンティクスであることに注意してください。

llvm.minnum.*’ とはいくつかの違いがあります。1) ‘llvm.minnum.*’ は、いずれかのオペランドが sNaN の場合、qNaN を返します。2) ‘llvm.minnum*’ は、+0.0 と -0.0 を比較した場合、どちらかを返す可能性があります。

llvm.maximumnum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.maximumnum を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.maximumnum.f32(float %Val0, float %Val1)
declare double    @llvm.maximumnum.f64(double %Val0, double %Val1)
declare x86_fp80  @llvm.maximumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
declare fp128     @llvm.maximumnum.f128(fp128 %Val0, fp128 %Val1)
declare ppc_fp128 @llvm.maximumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
概要:

llvm.maximumnum.*’ 組み込み関数は、2つの引数のうち大きい方を返し、NaN を伝播せず、-0.0 を +0.0 より小さいものとして扱います。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

両方のオペランドが NaN (sNaN を含む) の場合、qNaN を返します。一方のオペランドが NaN (sNaN を含む) で、もう一方のオペランドが数値の場合、その数値を返します。それ以外の場合は、2つの引数のうち大きい方を返します。この組み込み関数では、-0.0 は +0.0 より小さいと見なされます。

これらは IEEE 754-2019 で指定された maximumNumber のセマンティクスであることに注意してください。

llvm.maxnum.*’ とはいくつかの違いがあります。1) ‘llvm.maxnum.*’ は、いずれかのオペランドが sNaN の場合、qNaN を返します。2) ‘llvm.maxnum*’ は、+0.0 と -0.0 を比較した場合、どちらかを返す可能性があります。

llvm.copysign.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.copysign を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.copysign.f32(float  %Mag, float  %Sgn)
declare double    @llvm.copysign.f64(double %Mag, double %Sgn)
declare x86_fp80  @llvm.copysign.f80(x86_fp80  %Mag, x86_fp80  %Sgn)
declare fp128     @llvm.copysign.f128(fp128 %Mag, fp128 %Sgn)
declare ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128  %Mag, ppc_fp128  %Sgn)
概要:

llvm.copysign.*’ 組み込み関数は、最初のオペランドの絶対値と、2番目のオペランドの符号を持つ値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の copysign 関数と同じ値を返し、エラー条件も同じように処理します。返される値は、符号ビットを除いて、最初のオペランドと完全に同一です。特に、入力が NaN の場合、静音/シグナリングビットとペイロードは完全に保持されます。

llvm.floor.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.floor を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.floor.f32(float  %Val)
declare double    @llvm.floor.f64(double %Val)
declare x86_fp80  @llvm.floor.f80(x86_fp80  %Val)
declare fp128     @llvm.floor.f128(fp128 %Val)
declare ppc_fp128 @llvm.floor.ppcf128(ppc_fp128  %Val)
概要:

llvm.floor.*’ 組み込み関数は、オペランドの床関数を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の floor 関数と同じ値を返し、エラー条件も同じように処理します。

llvm.ceil.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.ceil を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.ceil.f32(float  %Val)
declare double    @llvm.ceil.f64(double %Val)
declare x86_fp80  @llvm.ceil.f80(x86_fp80  %Val)
declare fp128     @llvm.ceil.f128(fp128 %Val)
declare ppc_fp128 @llvm.ceil.ppcf128(ppc_fp128  %Val)
概要:

llvm.ceil.*’ 組み込み関数は、オペランドの天井関数を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の ceil 関数と同じ値を返し、エラー条件も同じように処理します。

llvm.trunc.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.trunc を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.trunc.f32(float  %Val)
declare double    @llvm.trunc.f64(double %Val)
declare x86_fp80  @llvm.trunc.f80(x86_fp80  %Val)
declare fp128     @llvm.trunc.f128(fp128 %Val)
declare ppc_fp128 @llvm.trunc.ppcf128(ppc_fp128  %Val)
概要:

llvm.trunc.*’ 組み込み関数は、オペランドを、オペランドの絶対値を超えない最も近い整数に丸めた値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の trunc 関数と同じ値を返し、エラー条件も同じように処理します。

llvm.rint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.rint を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.rint.f32(float  %Val)
declare double    @llvm.rint.f64(double %Val)
declare x86_fp80  @llvm.rint.f80(x86_fp80  %Val)
declare fp128     @llvm.rint.f128(fp128 %Val)
declare ppc_fp128 @llvm.rint.ppcf128(ppc_fp128  %Val)
概要:

llvm.rint.*’ 組み込み関数は、オペランドを最も近い整数に丸めた値を返します。オペランドが整数でない場合、不正確な浮動小数点例外が発生する可能性があります。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の rint 関数と同じ値を返し、エラー条件も同じように処理します。LLVM は デフォルトの浮動小数点環境 を想定しているため、丸めモードは「最近傍」に設定されていると想定され、中間の場合は偶数整数に丸められます。この仮定を回避するには、制約付き浮動小数点組み込み関数 を使用してください。

llvm.nearbyint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型または浮動小数点型のベクトルに対して llvm.nearbyint を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.nearbyint.f32(float  %Val)
declare double    @llvm.nearbyint.f64(double %Val)
declare x86_fp80  @llvm.nearbyint.f80(x86_fp80  %Val)
declare fp128     @llvm.nearbyint.f128(fp128 %Val)
declare ppc_fp128 @llvm.nearbyint.ppcf128(ppc_fp128  %Val)
概要:

llvm.nearbyint.*’ 組み込み関数は、オペランドを最も近い整数に丸めた値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の nearbyint 関数と同じ値を返し、エラー状態も同様に処理します。LLVM は デフォルトの浮動小数点環境 を想定しているため、丸めモードは「最近接」に設定されていると想定され、中間値は偶数整数に丸められます。この想定を回避するには、制約付き浮動小数点組み込み関数 を使用してください。

llvm.round.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。浮動小数点型または浮動小数点型のベクターに対して llvm.round を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.round.f32(float  %Val)
declare double    @llvm.round.f64(double %Val)
declare x86_fp80  @llvm.round.f80(x86_fp80  %Val)
declare fp128     @llvm.round.f128(fp128 %Val)
declare ppc_fp128 @llvm.round.ppcf128(ppc_fp128  %Val)
概要:

llvm.round.*’ 組み込み関数は、オペランドを最も近い整数に丸めた値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、libm の round 関数と同じ値を返し、エラー状態も同様に処理します。

llvm.roundeven.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。浮動小数点型または浮動小数点型のベクターに対して llvm.roundeven を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare float     @llvm.roundeven.f32(float  %Val)
declare double    @llvm.roundeven.f64(double %Val)
declare x86_fp80  @llvm.roundeven.f80(x86_fp80  %Val)
declare fp128     @llvm.roundeven.f128(fp128 %Val)
declare ppc_fp128 @llvm.roundeven.ppcf128(ppc_fp128  %Val)
概要:

llvm.roundeven.*’ 組み込み関数は、浮動小数点形式で、オペランドを最も近い整数に丸め、中間値は偶数 (つまり、偶数整数である最も近い値) に丸めた値を返します。

引数:

引数と戻り値は、同じ型の浮動小数点数です。

セマンティクス:

この関数は、IEEE-754 操作の roundToIntegralTiesToEven を実装します。また、浮動小数点例外を発生させないことを除いて、C 標準関数の roundeven と同じように動作します。

llvm.lround.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。浮動小数点型または浮動小数点型のベクターに対して llvm.lround を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare i32 @llvm.lround.i32.f32(float %Val)
declare i32 @llvm.lround.i32.f64(double %Val)
declare i32 @llvm.lround.i32.f80(float %Val)
declare i32 @llvm.lround.i32.f128(double %Val)
declare i32 @llvm.lround.i32.ppcf128(double %Val)

declare i64 @llvm.lround.i64.f32(float %Val)
declare i64 @llvm.lround.i64.f64(double %Val)
declare i64 @llvm.lround.i64.f80(float %Val)
declare i64 @llvm.lround.i64.f128(double %Val)
declare i64 @llvm.lround.i64.ppcf128(double %Val)
概要:

llvm.lround.*’ 組み込み関数は、オペランドをゼロから遠い方向に最も近い整数に丸めた値を返します。

引数:

引数は浮動小数点数で、戻り値は整数型です。

セマンティクス:

この関数は、libm の lround 関数と同じ値を返しますが、errno を設定しません。丸められた値が結果型に格納するには大きすぎる場合、戻り値は非決定的な値になります ( freeze poison に相当)。

llvm.llround.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点型に対して llvm.llround を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare i64 @llvm.lround.i64.f32(float %Val)
declare i64 @llvm.lround.i64.f64(double %Val)
declare i64 @llvm.lround.i64.f80(float %Val)
declare i64 @llvm.lround.i64.f128(double %Val)
declare i64 @llvm.lround.i64.ppcf128(double %Val)
概要:

llvm.llround.*’ 組み込み関数は、オペランドをゼロから遠い方向に最も近い整数に丸めた値を返します。

引数:

引数は浮動小数点数で、戻り値は整数型です。

セマンティクス:

この関数は、libm の llround 関数と同じ値を返しますが、errno を設定しません。丸められた値が結果型に格納するには大きすぎる場合、戻り値は非決定的な値になります ( freeze poison に相当)。

llvm.lrint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。浮動小数点型または浮動小数点型のベクターに対して llvm.lrint を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare i32 @llvm.lrint.i32.f32(float %Val)
declare i32 @llvm.lrint.i32.f64(double %Val)
declare i32 @llvm.lrint.i32.f80(float %Val)
declare i32 @llvm.lrint.i32.f128(double %Val)
declare i32 @llvm.lrint.i32.ppcf128(double %Val)

declare i64 @llvm.lrint.i64.f32(float %Val)
declare i64 @llvm.lrint.i64.f64(double %Val)
declare i64 @llvm.lrint.i64.f80(float %Val)
declare i64 @llvm.lrint.i64.f128(double %Val)
declare i64 @llvm.lrint.i64.ppcf128(double %Val)
概要:

llvm.lrint.*’ 組み込み関数は、オペランドを最も近い整数に丸めた値を返します。

引数:

引数は浮動小数点数で、戻り値は整数型です。

セマンティクス:

この関数は、libm の lrint 関数と同じ値を返しますが、errno を設定しません。丸められた値が結果型に格納するには大きすぎる場合、戻り値は非決定的な値になります ( freeze poison に相当)。

llvm.llrint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。浮動小数点型または浮動小数点型のベクターに対して llvm.llrint を使用できます。ただし、すべてのターゲットがすべての型をサポートしているわけではありません。

declare i64 @llvm.llrint.i64.f32(float %Val)
declare i64 @llvm.llrint.i64.f64(double %Val)
declare i64 @llvm.llrint.i64.f80(float %Val)
declare i64 @llvm.llrint.i64.f128(double %Val)
declare i64 @llvm.llrint.i64.ppcf128(double %Val)
概要:

llvm.llrint.*’ 組み込み関数は、オペランドを最も近い整数に丸めた値を返します。

引数:

引数は浮動小数点数で、戻り値は整数型です。

セマンティクス:

この関数は、libm の llrint 関数と同じ値を返しますが、errno を設定しません。丸められた値が結果型に格納するには大きすぎる場合、戻り値は非決定的な値になります ( freeze poison に相当)。

ビット操作組み込み関数

LLVM は、いくつかの重要なビット操作のための組み込み関数を提供しています。これらにより、いくつかのアルゴリズムの効率的なコード生成が可能になります。

llvm.bitreverse.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数型に対して bitreverse を使用できます。

declare i16 @llvm.bitreverse.i16(i16 <id>)
declare i32 @llvm.bitreverse.i32(i32 <id>)
declare i64 @llvm.bitreverse.i64(i64 <id>)
declare <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> <id>)
概要:

llvm.bitreverse’ 組み込み関数ファミリーは、整数値または整数値のベクターのビットパターンを反転するために使用されます。たとえば、0b101101100b01101101 になります。

セマンティクス:

llvm.bitreverse.iN 組み込み関数は、入力のビット M を出力のビット N-M-1 に移動した iN 値を返します。 llvm.bitreverse.v4i32 などのベクター組み込み関数は、要素ごとに動作し、要素の順序は影響を受けません。

llvm.bswap.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。偶数バイト数 (つまり、BitWidth % 16 == 0) の任意の整数型に対して bswap を使用できます。

declare i16 @llvm.bswap.i16(i16 <id>)
declare i32 @llvm.bswap.i32(i32 <id>)
declare i64 @llvm.bswap.i64(i64 <id>)
declare <4 x i32> @llvm.bswap.v4i32(<4 x i32> <id>)
概要:

llvm.bswap’ 組み込み関数ファミリーは、偶数バイト数 (16 ビットの正の倍数) の整数値または整数値のベクターをバイトスワップするために使用されます。

セマンティクス:

llvm.bswap.i16 組み込み関数は、入力 i16 の上位バイトと下位バイトをスワップした i16 値を返します。同様に、llvm.bswap.i32 組み込み関数は、入力 i32 の 4 つのバイトをスワップした i32 値を返します。そのため、入力バイトが 0、1、2、3 と番号付けされている場合、返される i32 は 3、2、1、0 の順序でバイトを持ちます。 llvm.bswap.i48llvm.bswap.i64、およびその他の組み込み関数は、この概念をそれぞれ追加の偶数バイト長 (6 バイト、8 バイトなど) に拡張します。 llvm.bswap.v4i32 などのベクター組み込み関数は、要素ごとに動作し、要素の順序は影響を受けません。

llvm.ctpop.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅、または整数要素を持つ任意のベクターに対して llvm.ctpop を使用できます。ただし、すべてのターゲットがすべてのビット幅またはベクター型をサポートしているわけではありません。

declare i8 @llvm.ctpop.i8(i8  <src>)
declare i16 @llvm.ctpop.i16(i16 <src>)
declare i32 @llvm.ctpop.i32(i32 <src>)
declare i64 @llvm.ctpop.i64(i64 <src>)
declare i256 @llvm.ctpop.i256(i256 <src>)
declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32> <src>)
概要:

llvm.ctpop’ 組み込み関数ファミリーは、値に設定されているビット数をカウントします。

引数:

唯一の引数は、カウントされる値です。引数は、任意の整数型、または整数要素を持つベクターにすることができます。戻り値の型は、引数の型と一致する必要があります。

セマンティクス:

llvm.ctpop’ 組み込み関数は、変数内、またはベクターの各要素内の 1 の数をカウントします。

llvm.ctlz.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅、または要素が整数の任意のベクターに対して llvm.ctlz を使用できます。ただし、すべてのターゲットがすべてのビット幅またはベクター型をサポートしているわけではありません。

declare i8   @llvm.ctlz.i8  (i8   <src>, i1 <is_zero_poison>)
declare <2 x i37> @llvm.ctlz.v2i37(<2 x i37> <src>, i1 <is_zero_poison>)
概要:

llvm.ctlz」ファミリの組み込み関数は、変数の先頭のゼロの数をカウントします。

引数:

最初の引数は、カウントする値です。この引数は、任意の整数型、または整数要素型を持つベクトルにすることができます。戻り値の型は、最初の引数の型と一致する必要があります。

2 番目の引数は、最初の引数がゼロの場合に、組み込み関数が有効な結果を返すかどうかを示す定数フラグです。最初の引数がゼロで、2 番目の引数が true の場合、結果は poison になります。歴史的に、一部のアーキテクチャでは、ゼロ値に対して効率的に定義された結果を提供していなかったため、多くのアルゴリズムはゼロ値の入力を回避することを前提としています。

セマンティクス:

llvm.ctlz」組み込み関数は、変数またはベクトルの各要素内の先頭 (最上位) のゼロをカウントします。src == 0 の場合、is_zero_poison == 0 の場合は、結果は src の型のビットサイズになり、それ以外の場合は poison になります。たとえば、llvm.ctlz(i32 2) = 30 です。

llvm.cttz.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅、または整数要素の任意のベクトルに対して llvm.cttz を使用できます。ただし、すべてのターゲットがすべてのビット幅またはベクトル型をサポートしているわけではありません。

declare i42   @llvm.cttz.i42  (i42   <src>, i1 <is_zero_poison>)
declare <2 x i32> @llvm.cttz.v2i32(<2 x i32> <src>, i1 <is_zero_poison>)
概要:

llvm.cttz」ファミリの組み込み関数は、末尾のゼロの数をカウントします。

引数:

最初の引数は、カウントする値です。この引数は、任意の整数型、または整数要素型を持つベクトルにすることができます。戻り値の型は、最初の引数の型と一致する必要があります。

2 番目の引数は、最初の引数がゼロの場合に、組み込み関数が有効な結果を返すかどうかを示す定数フラグです。最初の引数がゼロで、2 番目の引数が true の場合、結果は poison になります。歴史的に、一部のアーキテクチャでは、ゼロ値に対して効率的に定義された結果を提供していなかったため、多くのアルゴリズムはゼロ値の入力を回避することを前提としています。

セマンティクス:

llvm.cttz」組み込み関数は、変数またはベクトルの各要素内の末尾 (最下位) のゼロをカウントします。src == 0 の場合、is_zero_poison == 0 の場合は、結果は src の型のビットサイズになり、それ以外の場合は poison になります。たとえば、llvm.cttz(2) = 1 です。

llvm.fshl.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅、または整数要素の任意のベクトルに対して llvm.fshl を使用できます。ただし、すべてのターゲットがすべてのビット幅またはベクトル型をサポートしているわけではありません。

declare i8  @llvm.fshl.i8 (i8 %a, i8 %b, i8 %c)
declare i64 @llvm.fshl.i64(i64 %a, i64 %b, i64 %c)
declare <2 x i32> @llvm.fshl.v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c)
概要:

llvm.fshl」ファミリの組み込み関数は、ファネルシフト左を実行します。最初の 2 つの値は { %a : %b } として連結されます (%a はワイド値の最上位ビットです)。結合された値は左にシフトされ、最上位ビットが抽出されて、元の引数と同じサイズの出力を生成します。最初の 2 つの引数が同一の場合、これは左回転操作と同等です。ベクトル型の場合、操作はベクトルの各要素に対して発生します。シフト引数は、引数の要素サイズの剰余としての符号なし量として扱われます。

引数:

最初の 2 つの引数は、連結する値です。3 番目の引数は、シフト量です。引数は、任意の整数型、または整数要素型を持つベクトルにすることができます。すべての引数と戻り値は、同じ型を持つ必要があります。

例:
%r = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %z)  ; %r = i8: msb_extract((concat(x, y) << (z % 8)), 8)
%r = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 15)  ; %r = i8: 128 (0b10000000)
%r = call i8 @llvm.fshl.i8(i8 15, i8 15, i8 11)  ; %r = i8: 120 (0b01111000)
%r = call i8 @llvm.fshl.i8(i8 0, i8 255, i8 8)   ; %r = i8: 0   (0b00000000)

llvm.fshr.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅、または整数要素の任意のベクトルに対して llvm.fshr を使用できます。ただし、すべてのターゲットがすべてのビット幅またはベクトル型をサポートしているわけではありません。

declare i8  @llvm.fshr.i8 (i8 %a, i8 %b, i8 %c)
declare i64 @llvm.fshr.i64(i64 %a, i64 %b, i64 %c)
declare <2 x i32> @llvm.fshr.v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c)
概要:

llvm.fshr」ファミリの組み込み関数は、ファネルシフト右を実行します。最初の 2 つの値は { %a : %b } として連結されます (%a はワイド値の最上位ビットです)。結合された値は右にシフトされ、最下位ビットが抽出されて、元の引数と同じサイズの出力を生成します。最初の 2 つの引数が同一の場合、これは右回転操作と同等です。ベクトル型の場合、操作はベクトルの各要素に対して発生します。シフト引数は、引数の要素サイズの剰余としての符号なし量として扱われます。

引数:

最初の 2 つの引数は、連結する値です。3 番目の引数は、シフト量です。引数は、任意の整数型、または整数要素型を持つベクトルにすることができます。すべての引数と戻り値は、同じ型を持つ必要があります。

例:
%r = call i8 @llvm.fshr.i8(i8 %x, i8 %y, i8 %z)  ; %r = i8: lsb_extract((concat(x, y) >> (z % 8)), 8)
%r = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 15)  ; %r = i8: 254 (0b11111110)
%r = call i8 @llvm.fshr.i8(i8 15, i8 15, i8 11)  ; %r = i8: 225 (0b11100001)
%r = call i8 @llvm.fshr.i8(i8 0, i8 255, i8 8)   ; %r = i8: 255 (0b11111111)

オーバーフロー付きの算術組み込み関数

LLVM は、高速な算術オーバーフローチェックのための組み込み関数を提供します。

これらの各組み込み関数は、2 つの要素を持つ構造体を返します。この構造体の最初の要素には、対応する算術演算の結果が 2n を法として含まれています。ここで、n は結果のビット幅です。したがって、たとえば、llvm.sadd.with.overflow.i32 によって返される構造体の最初の要素は、同じオペランドを持つ 32 ビットの add 命令の結果と常に同じです。ここで、addnsw または nuw フラグによって変更されていません

結果の 2 番目の要素は、算術演算がオーバーフローした場合は 1、それ以外の場合は 0 の i1 です。オペランド A および B の任意の値、およびオペランドの幅よりも大きい任意の N に対して、ext(A op B) to iN(ext(A) to iN) op (ext(B) to iN) と等しくない場合、操作はオーバーフローします。ここで、ext は、符号付きオーバーフローの場合は sext、符号なしオーバーフローの場合は zextop は基になる算術演算です。

これらの組み込み関数の動作は、すべての引数値に対して明確に定義されています。

llvm.sadd.with.overflow.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.sadd.with.overflow を使用できます。

declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.sadd.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.sadd.with.overflow」ファミリの組み込み関数は、2 つの引数の符号付き加算を実行し、符号付き加算中にオーバーフローが発生したかどうかを示します。

引数:

引数 (%a および %b) と結果構造体の最初の要素は、任意のビット幅の整数型にすることができますが、同じビット幅を持つ必要があります。結果構造体の 2 番目の要素は、i1 型である必要があります。%a%b は、符号付き加算される 2 つの値です。

セマンティクス:

llvm.sadd.with.overflow」ファミリの組み込み関数は、2 つの変数の符号付き加算を実行します。構造体を返します。最初の要素は符号付き加算で、2 番目の要素は符号付き加算がオーバーフローしたかどうかを指定するビットです。

例:
%res = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %overflow, label %normal

llvm.uadd.with.overflow.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.uadd.with.overflow を使用できます。

declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.uadd.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.uadd.with.overflow’ 系の組み込み関数は、2つの引数の符号なし加算を実行し、符号なし加算中にキャリーが発生したかどうかを示します。

引数:

引数(%aと%b)と結果構造体の最初の要素は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。結果構造体の2番目の要素は、i1型である必要があります。%a%bは、符号なし加算される2つの値です。

セマンティクス:

llvm.uadd.with.overflow’ 系の組み込み関数は、2つの引数の符号なし加算を実行します。これらの関数は構造体を返します。構造体の最初の要素は合計で、2番目の要素は符号なし加算の結果キャリーが発生したかどうかを示すビットです。

例:
%res = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %carry, label %normal

llvm.ssub.with.overflow.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.ssub.with.overflow は、任意の整数ビット幅または整数ベクターで使用できます。

declare {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.ssub.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.ssub.with.overflow’ 系の組み込み関数は、2つの引数の符号付き減算を実行し、符号付き減算中にオーバーフローが発生したかどうかを示します。

引数:

引数(%aと%b)と結果構造体の最初の要素は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。結果構造体の2番目の要素は、i1型である必要があります。%a%bは、符号付き減算される2つの値です。

セマンティクス:

llvm.ssub.with.overflow’ 系の組み込み関数は、2つの引数の符号付き減算を実行します。これらの関数は構造体を返します。構造体の最初の要素は減算結果で、2番目の要素は符号付き減算の結果オーバーフローが発生したかどうかを示すビットです。

例:
%res = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %overflow, label %normal

llvm.usub.with.overflow.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.usub.with.overflow は、任意の整数ビット幅または整数ベクターで使用できます。

declare {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.usub.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.usub.with.overflow’ 系の組み込み関数は、2つの引数の符号なし減算を実行し、符号なし減算中にオーバーフローが発生したかどうかを示します。

引数:

引数(%aと%b)と結果構造体の最初の要素は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。結果構造体の2番目の要素は、i1型である必要があります。%a%bは、符号なし減算される2つの値です。

セマンティクス:

llvm.usub.with.overflow’ 系の組み込み関数は、2つの引数の符号なし減算を実行します。これらの関数は構造体を返します。構造体の最初の要素は減算結果で、2番目の要素は符号なし減算の結果オーバーフローが発生したかどうかを示すビットです。

例:
%res = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %overflow, label %normal

llvm.smul.with.overflow.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.smul.with.overflow は、任意の整数ビット幅または整数ベクターで使用できます。

declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.smul.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.smul.with.overflow’ 系の組み込み関数は、2つの引数の符号付き乗算を実行し、符号付き乗算中にオーバーフローが発生したかどうかを示します。

引数:

引数(%aと%b)と結果構造体の最初の要素は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。結果構造体の2番目の要素は、i1型である必要があります。%a%bは、符号付き乗算される2つの値です。

セマンティクス:

llvm.smul.with.overflow’ 系の組み込み関数は、2つの引数の符号付き乗算を実行します。これらの関数は構造体を返します。構造体の最初の要素は乗算結果で、2番目の要素は符号付き乗算の結果オーバーフローが発生したかどうかを示すビットです。

例:
%res = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %overflow, label %normal

llvm.umul.with.overflow.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。llvm.umul.with.overflow は、任意の整数ビット幅または整数ベクターで使用できます。

declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
declare {i64, i1} @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
declare {<4 x i32>, <4 x i1>} @llvm.umul.with.overflow.v4i32(<4 x i32> %a, <4 x i32> %b)
概要:

llvm.umul.with.overflow’ 系の組み込み関数は、2つの引数の符号なし乗算を実行し、符号なし乗算中にオーバーフローが発生したかどうかを示します。

引数:

引数(%aと%b)と結果構造体の最初の要素は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。結果構造体の2番目の要素は、i1型である必要があります。%a%bは、符号なし乗算される2つの値です。

セマンティクス:

llvm.umul.with.overflow’ 系の組み込み関数は、2つの引数の符号なし乗算を実行します。これらの関数は構造体を返します。構造体の最初の要素は乗算結果で、2番目の要素は符号なし乗算の結果オーバーフローが発生したかどうかを示すビットです。

例:
%res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
%sum = extractvalue {i32, i1} %res, 0
%obit = extractvalue {i32, i1} %res, 1
br i1 %obit, label %overflow, label %normal

飽和演算組み込み関数

飽和演算は、演算が最小値と最大値の間の固定範囲に制限される演算の一種です。演算の結果が最大値より大きい場合、結果はこの最大値に設定(または「クランプ」)されます。最小値より小さい場合は、この最小値にクランプされます。

llvm.sadd.sat.*’ 組み込み関数

構文

これはオーバーロードされた組み込み関数です。llvm.sadd.sat は、任意の整数ビット幅または整数ベクターで使用できます。

declare i16 @llvm.sadd.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.sadd.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.sadd.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.sadd.sat’ 系の組み込み関数は、2つの引数に対して符号付き飽和加算を実行します。

引数

引数(%aと%b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a%bは、符号付き加算される2つの値です。

セマンティクス:

この演算がクランプできる最大値は、引数のビット幅で表現できる最大の符号付き値です。最小値は、このビット幅で表現できる最小の符号付き値です。

%res = call i4 @llvm.sadd.sat.i4(i4 1, i4 2)  ; %res = 3
%res = call i4 @llvm.sadd.sat.i4(i4 5, i4 6)  ; %res = 7
%res = call i4 @llvm.sadd.sat.i4(i4 -4, i4 2)  ; %res = -2
%res = call i4 @llvm.sadd.sat.i4(i4 -4, i4 -5)  ; %res = -8

llvm.uadd.sat.*’ 組み込み関数

構文

これはオーバーロードされた組み込み関数です。llvm.uadd.sat は、任意の整数ビット幅または整数ベクターで使用できます。

declare i16 @llvm.uadd.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.uadd.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.uadd.sat’ 系の組み込み関数は、2つの引数に対して符号なし飽和加算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a%b は、符号なし加算が行われる 2 つの値です。

意味:

この演算がクランプできる最大値は、引数のビット幅で表現可能な最大の符号なし値です。これは符号なし演算であるため、結果がゼロに向かって飽和することはありません。

%res = call i4 @llvm.uadd.sat.i4(i4 1, i4 2)  ; %res = 3
%res = call i4 @llvm.uadd.sat.i4(i4 5, i4 6)  ; %res = 11
%res = call i4 @llvm.uadd.sat.i4(i4 8, i4 8)  ; %res = 15

llvm.ssub.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.ssub.sat を使用できます。

declare i16 @llvm.ssub.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.ssub.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.ssub.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.ssub.sat」組み込み関数群は、2 つの引数に対して符号付き飽和減算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a%b は、符号付き減算が行われる 2 つの値です。

意味:

この演算がクランプできる最大値は、引数のビット幅で表現できる最大の符号付き値です。最小値は、このビット幅で表現できる最小の符号付き値です。

%res = call i4 @llvm.ssub.sat.i4(i4 2, i4 1)  ; %res = 1
%res = call i4 @llvm.ssub.sat.i4(i4 2, i4 6)  ; %res = -4
%res = call i4 @llvm.ssub.sat.i4(i4 -4, i4 5)  ; %res = -8
%res = call i4 @llvm.ssub.sat.i4(i4 4, i4 -5)  ; %res = 7

llvm.usub.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.usub.sat を使用できます。

declare i16 @llvm.usub.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.usub.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.usub.sat」組み込み関数群は、2 つの引数に対して符号なし飽和減算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a%b は、符号なし減算が行われる 2 つの値です。

意味:

この演算がクランプできる最小値は 0 であり、これは符号なし引数のビット幅で表現可能な最小の符号なし値です。これは符号なし演算であるため、結果がこのビット幅で表現可能な最大値に向かって飽和することはありません。

%res = call i4 @llvm.usub.sat.i4(i4 2, i4 1)  ; %res = 1
%res = call i4 @llvm.usub.sat.i4(i4 2, i4 6)  ; %res = 0

llvm.sshl.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意のビット幅の整数または整数のベクトルに対して llvm.sshl.sat を使用できます。

declare i16 @llvm.sshl.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.sshl.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.sshl.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.sshl.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.sshl.sat」組み込み関数群は、最初の引数に対して符号付き飽和左シフトを実行します。

引数

引数(%a%b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a はシフトされる値で、%b はシフト量です。b が引数の整数ビット幅以上である(静的または動的に)場合、結果はポイズン値になります。引数がベクトルの場合、a の各ベクトル要素は、b の対応するシフト量でシフトされます。

意味:

この演算がクランプできる最大値は、引数のビット幅で表現できる最大の符号付き値です。最小値は、このビット幅で表現できる最小の符号付き値です。

%res = call i4 @llvm.sshl.sat.i4(i4 2, i4 1)  ; %res = 4
%res = call i4 @llvm.sshl.sat.i4(i4 2, i4 2)  ; %res = 7
%res = call i4 @llvm.sshl.sat.i4(i4 -5, i4 1)  ; %res = -8
%res = call i4 @llvm.sshl.sat.i4(i4 -1, i4 1)  ; %res = -2

llvm.ushl.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意のビット幅の整数または整数のベクトルに対して llvm.ushl.sat を使用できます。

declare i16 @llvm.ushl.sat.i16(i16 %a, i16 %b)
declare i32 @llvm.ushl.sat.i32(i32 %a, i32 %b)
declare i64 @llvm.ushl.sat.i64(i64 %a, i64 %b)
declare <4 x i32> @llvm.ushl.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
概要

llvm.ushl.sat」組み込み関数群は、最初の引数に対して符号なし飽和左シフトを実行します。

引数

引数(%a%b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。%a はシフトされる値で、%b はシフト量です。b が引数の整数ビット幅以上である(静的または動的に)場合、結果はポイズン値になります。引数がベクトルの場合、a の各ベクトル要素は、b の対応するシフト量でシフトされます。

意味:

この演算がクランプできる最大値は、引数のビット幅で表現可能な最大の符号なし値です。

%res = call i4 @llvm.ushl.sat.i4(i4 2, i4 1)  ; %res = 4
%res = call i4 @llvm.ushl.sat.i4(i4 3, i4 3)  ; %res = 15

固定小数点演算組み込み関数

固定小数点数は、基数点(小数点 '.' に相当)の後ろに固定数の桁を持つ数の実数データ型を表します。基数点の後ろの桁数は、スケールと呼ばれます。これらは、特定の精度で小数値を表現するのに役立ちます。次の組み込み関数は、3 番目の引数で指定された同じスケールの 2 つのオペランドに対して固定小数点演算を実行します。

llvm.*mul.fix 組み込み関数群は、スケールされた整数による固定小数点数の乗算を表します。したがって、固定小数点乗算は次のように表すことができます。

%result = call i4 @llvm.smul.fix.i4(i4 %a, i4 %b, i32 %scale)

; Expands to
%a2 = sext i4 %a to i8
%b2 = sext i4 %b to i8
%mul = mul nsw nuw i8 %a2, %b2
%scale2 = trunc i32 %scale to i8
%r = ashr i8 %mul, i8 %scale2  ; this is for a target rounding down towards negative infinity
%result = trunc i8 %r to i4

llvm.*div.fix 組み込み関数群は、スケールされた整数による固定小数点数の除算を表します。固定小数点除算は次のように表すことができます。

%result call i4 @llvm.sdiv.fix.i4(i4 %a, i4 %b, i32 %scale)

; Expands to
%a2 = sext i4 %a to i8
%b2 = sext i4 %b to i8
%scale2 = trunc i32 %scale to i8
%a3 = shl i8 %a2, %scale2
%r = sdiv i8 %a3, %b2 ; this is for a target rounding towards zero
%result = trunc i8 %r to i4

これらの各関数について、結果が提供されたスケールで正確に表現できない場合、結果は丸められます。優先される丸めはターゲットによって異なる可能性があるため、丸めは指定されていません。丸めは、ターゲットフックを通じて指定されます。異なるパイプラインは、このフックで指定された丸めを使用し、提供されている場合は、これを正規化または最適化する必要があります。定数畳み込み、命令結合、KnownBits、ValueTrackingなどの操作も、提供されている場合はこのフックを使用し、丸めの方向を想定しないようにする必要があります。丸められた結果は、常に真の結果から 1 単位の精度内にある必要があります。つまり、返された結果と真の結果の間の誤差は、1/2^(スケール) 未満でなければなりません。

llvm.smul.fix.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.smul.fix を使用できます。

declare i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.smul.fix.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.smul.fix.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.smul.fix.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.smul.fix」組み込み関数群は、同じスケールの 2 つの引数に対して符号付き固定小数点乗算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。引数は、同じ長さとintサイズのintベクトルでも使用できます。%a%b は、符号付き固定小数点乗算が行われる 2 つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味:

この演算は、指定されたスケールの 2 つの引数に対して固定小数点乗算を実行します。結果は、3 番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

結果値が固定小数点型の範囲内に収まらない場合は、未定義の動作になります。

%res = call i4 @llvm.smul.fix.i4(i4 3, i4 2, i32 0)  ; %res = 6 (2 x 3 = 6)
%res = call i4 @llvm.smul.fix.i4(i4 3, i4 2, i32 1)  ; %res = 3 (1.5 x 1 = 1.5)
%res = call i4 @llvm.smul.fix.i4(i4 3, i4 -2, i32 1)  ; %res = -3 (1.5 x -1 = -1.5)

; The result in the following could be rounded up to -2 or down to -2.5
%res = call i4 @llvm.smul.fix.i4(i4 3, i4 -3, i32 1)  ; %res = -5 (or -4) (1.5 x -1.5 = -2.25)

llvm.umul.fix.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.umul.fix を使用できます。

declare i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.umul.fix.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.umul.fix.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.umul.fix.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.umul.fix」組み込み関数群は、同じスケールの 2 つの引数に対して符号なし固定小数点乗算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にできますが、同じビット幅である必要があります。引数は、同じ長さとintサイズのintベクトルでも使用できます。%a%b は、符号なし固定小数点乗算が行われる 2 つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味:

この演算は、指定されたスケールの 2 つの引数に対して符号なし固定小数点乗算を実行します。結果は、3 番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

結果値が固定小数点型の範囲内に収まらない場合は、未定義の動作になります。

%res = call i4 @llvm.umul.fix.i4(i4 3, i4 2, i32 0)  ; %res = 6 (2 x 3 = 6)
%res = call i4 @llvm.umul.fix.i4(i4 3, i4 2, i32 1)  ; %res = 3 (1.5 x 1 = 1.5)

; The result in the following could be rounded down to 3.5 or up to 4
%res = call i4 @llvm.umul.fix.i4(i4 15, i4 1, i32 1)  ; %res = 7 (or 8) (7.5 x 0.5 = 3.75)

llvm.smul.fix.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数のベクトルに対して llvm.smul.fix.sat を使用できます。

declare i16 @llvm.smul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.smul.fix.sat.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.smul.fix.sat.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.smul.fix.sat.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.smul.fix.sat」系の組み込み関数は、同じスケールの2つの引数に対して、符号付き固定小数点飽和乗算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。%a%b は、符号付き固定小数点乗算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの 2 つの引数に対して固定小数点乗算を実行します。結果は、3 番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

この演算がクランプできる最大値は、最初の2つの引数のビット幅で表現可能な最大の符号付き値です。最小値は、このビット幅で表現可能な最小の符号付き値です。

%res = call i4 @llvm.smul.fix.sat.i4(i4 3, i4 2, i32 0)  ; %res = 6 (2 x 3 = 6)
%res = call i4 @llvm.smul.fix.sat.i4(i4 3, i4 2, i32 1)  ; %res = 3 (1.5 x 1 = 1.5)
%res = call i4 @llvm.smul.fix.sat.i4(i4 3, i4 -2, i32 1)  ; %res = -3 (1.5 x -1 = -1.5)

; The result in the following could be rounded up to -2 or down to -2.5
%res = call i4 @llvm.smul.fix.sat.i4(i4 3, i4 -3, i32 1)  ; %res = -5 (or -4) (1.5 x -1.5 = -2.25)

; Saturation
%res = call i4 @llvm.smul.fix.sat.i4(i4 7, i4 2, i32 0)  ; %res = 7
%res = call i4 @llvm.smul.fix.sat.i4(i4 7, i4 4, i32 2)  ; %res = 7
%res = call i4 @llvm.smul.fix.sat.i4(i4 -8, i4 5, i32 2)  ; %res = -8
%res = call i4 @llvm.smul.fix.sat.i4(i4 -8, i4 -2, i32 1)  ; %res = 7

; Scale can affect the saturation result
%res = call i4 @llvm.smul.fix.sat.i4(i4 2, i4 4, i32 0)  ; %res = 7 (2 x 4 -> clamped to 7)
%res = call i4 @llvm.smul.fix.sat.i4(i4 2, i4 4, i32 1)  ; %res = 4 (1 x 2 = 2)

llvm.umul.fix.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数ベクターに対して llvm.umul.fix.sat を使用できます。

declare i16 @llvm.umul.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.umul.fix.sat.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.umul.fix.sat.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.umul.fix.sat.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.umul.fix.sat」系の組み込み関数は、同じスケールの2つの引数に対して、符号なし固定小数点飽和乗算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。%a%b は、符号なし固定小数点乗算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの 2 つの引数に対して固定小数点乗算を実行します。結果は、3 番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

この演算がクランプできる最大値は、最初の2つの引数のビット幅で表現可能な最大の符号なし値です。最小値は、このビット幅で表現可能な最小の符号なし値(ゼロ)です。

%res = call i4 @llvm.umul.fix.sat.i4(i4 3, i4 2, i32 0)  ; %res = 6 (2 x 3 = 6)
%res = call i4 @llvm.umul.fix.sat.i4(i4 3, i4 2, i32 1)  ; %res = 3 (1.5 x 1 = 1.5)

; The result in the following could be rounded down to 2 or up to 2.5
%res = call i4 @llvm.umul.fix.sat.i4(i4 3, i4 3, i32 1)  ; %res = 4 (or 5) (1.5 x 1.5 = 2.25)

; Saturation
%res = call i4 @llvm.umul.fix.sat.i4(i4 8, i4 2, i32 0)  ; %res = 15 (8 x 2 -> clamped to 15)
%res = call i4 @llvm.umul.fix.sat.i4(i4 8, i4 8, i32 2)  ; %res = 15 (2 x 2 -> clamped to 3.75)

; Scale can affect the saturation result
%res = call i4 @llvm.umul.fix.sat.i4(i4 2, i4 4, i32 0)  ; %res = 7 (2 x 4 -> clamped to 7)
%res = call i4 @llvm.umul.fix.sat.i4(i4 2, i4 4, i32 1)  ; %res = 4 (1 x 2 = 2)

llvm.sdiv.fix.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数ベクターに対して llvm.sdiv.fix を使用できます。

declare i16 @llvm.sdiv.fix.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.sdiv.fix.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.sdiv.fix.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.sdiv.fix.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.sdiv.fix」系の組み込み関数は、同じスケールの2つの引数に対して、符号付き固定小数点除算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。引数は、同じ長さと int サイズの int ベクターでも機能する場合があります。%a%b は、符号付き固定小数点除算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの2つの引数に対して固定小数点除算を実行します。結果も、3番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

結果の値が固定小数点型の範囲に収まらない場合、または2番目の引数がゼロの場合は、未定義の動作になります。

%res = call i4 @llvm.sdiv.fix.i4(i4 6, i4 2, i32 0)  ; %res = 3 (6 / 2 = 3)
%res = call i4 @llvm.sdiv.fix.i4(i4 6, i4 4, i32 1)  ; %res = 3 (3 / 2 = 1.5)
%res = call i4 @llvm.sdiv.fix.i4(i4 3, i4 -2, i32 1) ; %res = -3 (1.5 / -1 = -1.5)

; The result in the following could be rounded up to 1 or down to 0.5
%res = call i4 @llvm.sdiv.fix.i4(i4 3, i4 4, i32 1)  ; %res = 2 (or 1) (1.5 / 2 = 0.75)

llvm.udiv.fix.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数ベクターに対して llvm.udiv.fix を使用できます。

declare i16 @llvm.udiv.fix.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.udiv.fix.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.udiv.fix.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.udiv.fix.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.udiv.fix」系の組み込み関数は、同じスケールの2つの引数に対して、符号なし固定小数点除算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。引数は、同じ長さと int サイズの int ベクターでも機能する場合があります。%a%b は、符号なし固定小数点除算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの2つの引数に対して固定小数点除算を実行します。結果も、3番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

結果の値が固定小数点型の範囲に収まらない場合、または2番目の引数がゼロの場合は、未定義の動作になります。

%res = call i4 @llvm.udiv.fix.i4(i4 6, i4 2, i32 0)  ; %res = 3 (6 / 2 = 3)
%res = call i4 @llvm.udiv.fix.i4(i4 6, i4 4, i32 1)  ; %res = 3 (3 / 2 = 1.5)
%res = call i4 @llvm.udiv.fix.i4(i4 1, i4 -8, i32 4) ; %res = 2 (0.0625 / 0.5 = 0.125)

; The result in the following could be rounded up to 1 or down to 0.5
%res = call i4 @llvm.udiv.fix.i4(i4 3, i4 4, i32 1)  ; %res = 2 (or 1) (1.5 / 2 = 0.75)

llvm.sdiv.fix.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数ベクターに対して llvm.sdiv.fix.sat を使用できます。

declare i16 @llvm.sdiv.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.sdiv.fix.sat.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.sdiv.fix.sat.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.sdiv.fix.sat.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.sdiv.fix.sat」系の組み込み関数は、同じスケールの2つの引数に対して、符号付き固定小数点飽和除算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。%a%b は、符号付き固定小数点除算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの2つの引数に対して固定小数点除算を実行します。結果も、3番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

この演算がクランプできる最大値は、最初の2つの引数のビット幅で表現可能な最大の符号付き値です。最小値は、このビット幅で表現可能な最小の符号付き値です。

2番目の引数がゼロの場合、未定義の動作になります。

%res = call i4 @llvm.sdiv.fix.sat.i4(i4 6, i4 2, i32 0)  ; %res = 3 (6 / 2 = 3)
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 6, i4 4, i32 1)  ; %res = 3 (3 / 2 = 1.5)
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 3, i4 -2, i32 1) ; %res = -3 (1.5 / -1 = -1.5)

; The result in the following could be rounded up to 1 or down to 0.5
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 3, i4 4, i32 1)  ; %res = 2 (or 1) (1.5 / 2 = 0.75)

; Saturation
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 -8, i4 -1, i32 0)  ; %res = 7 (-8 / -1 = 8 => 7)
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 4, i4 2, i32 2)  ; %res = 7 (1 / 0.5 = 2 => 1.75)
%res = call i4 @llvm.sdiv.fix.sat.i4(i4 -4, i4 1, i32 2)  ; %res = -8 (-1 / 0.25 = -4 => -2)

llvm.udiv.fix.sat.*」組み込み関数

構文

これはオーバーロードされた組み込み関数です。任意の整数ビット幅または整数ベクターに対して llvm.udiv.fix.sat を使用できます。

declare i16 @llvm.udiv.fix.sat.i16(i16 %a, i16 %b, i32 %scale)
declare i32 @llvm.udiv.fix.sat.i32(i32 %a, i32 %b, i32 %scale)
declare i64 @llvm.udiv.fix.sat.i64(i64 %a, i64 %b, i32 %scale)
declare <4 x i32> @llvm.udiv.fix.sat.v4i32(<4 x i32> %a, <4 x i32> %b, i32 %scale)
概要

llvm.udiv.fix.sat」系の組み込み関数は、同じスケールの2つの引数に対して、符号なし固定小数点飽和除算を実行します。

引数

引数(%a と %b)と結果は、任意のビット幅の整数型にすることができますが、同じビット幅でなければなりません。%a%b は、符号なし固定小数点除算を受ける2つの値です。引数 %scale は両方のオペランドのスケールを表し、定数整数である必要があります。

意味論:

この演算は、指定されたスケールの2つの引数に対して固定小数点除算を実行します。結果も、3番目の引数で指定された同じスケールで返されます。

結果値を指定されたスケールで正確に表現できない場合、値は最も近い表現可能な値に切り上げまたは切り下げられます。丸めの方向は指定されていません。

この演算がクランプできる最大値は、最初の2つの引数のビット幅で表現可能な最大の符号なし値です。最小値は、このビット幅で表現可能な最小の符号なし値(ゼロ)です。

2番目の引数がゼロの場合、未定義の動作になります。

%res = call i4 @llvm.udiv.fix.sat.i4(i4 6, i4 2, i32 0)  ; %res = 3 (6 / 2 = 3)
%res = call i4 @llvm.udiv.fix.sat.i4(i4 6, i4 4, i32 1)  ; %res = 3 (3 / 2 = 1.5)

; The result in the following could be rounded down to 0.5 or up to 1
%res = call i4 @llvm.udiv.fix.sat.i4(i4 3, i4 4, i32 1)  ; %res = 1 (or 2) (1.5 / 2 = 0.75)

; Saturation
%res = call i4 @llvm.udiv.fix.sat.i4(i4 8, i4 2, i32 2)  ; %res = 15 (2 / 0.5 = 4 => 3.75)

特殊な算術組み込み関数

llvm.canonicalize.*」組み込み関数

構文:
declare float @llvm.canonicalize.f32(float %a)
declare double @llvm.canonicalize.f64(double %b)
概要:

llvm.canonicalize.*」組み込み関数は、浮動小数点数のプラットフォーム固有の正規エンコーディングを返します。この正規化は、frexpなどの特定の数値プリミティブを実装するのに役立ちます。正規エンコーディングは、IEEE-754-2008で次のように定義されています。

2.1.8 canonical encoding: The preferred encoding of a floating-point
representation in a format. Applied to declets, significands of finite
numbers, infinities, and NaNs, especially in decimal formats.

この演算は、浮動小数点値を同じ形式にIEEE-754-2008で変換することと同等と見なすこともできます。NaNはセクション6.2に従って処理されます。

非正規エンコーディングの例

  • x87疑似非正規数、疑似NaN、疑似無限大、非正規数。これらは、ハードウェア固有のプロトコルに従って正規表現に変換されます。

  • 多くの正規の10進浮動小数点数には、非正規の代替エンコーディングがあります。

  • GPUやARMv7 NEONなど、一部のマシンでは非正規値をサポートしていません。これらはゼロの非正規エンコーディングとして扱われ、この演算によって同じ符号のゼロにフラッシュされます。

IEEE-754-2008 6.2に従って、デフォルトの例外処理でシグナリングNaNをサポートするシステムは、無効な例外を通知し、quiet NaNの結果を生成する必要があります。

この関数は、コンパイラーが演算を定数に畳み込まないことを条件に、常に1.0による乗算として実装できるはずです。同様に、1.0による除算と llvm.minnum(x, x) は可能な実装です。丸めモードが-無限大でないことを条件に、-0.0との加算も十分です。

@llvm.canonicalize は等価関係を保持する必要があります。つまり

  • (@llvm.canonicalize(x) == x)(x == x) と同等です

  • (@llvm.canonicalize(x) == @llvm.canonicalize(y))(x == y) と同等です

さらに、ゼロの符号は保存する必要があります:@llvm.canonicalize(-0.0) = -0.0 および @llvm.canonicalize(+0.0) = +0.0

NaNのペイロードビットは、2つの例外を除いて保存する必要があります。1つ目は、NaNの単一の正規表現のみを使用する環境では、上記の正規化を実行する必要があります。2つ目は、SNaNは通常の方法に従って静音化する必要があります。

正規化演算は、以下の場合に最適化される可能性があります

  • 入力が正規であるとわかっている場合。たとえば、標準で正規である必要がある浮動小数点演算によって生成された場合。

  • 結果が他の浮動小数点演算によってのみ消費される(または融合される)場合。つまり、浮動小数点値のビットは調べられません。

llvm.fmuladd.*」組み込み関数

構文:
declare float @llvm.fmuladd.f32(float %a, float %b, float %c)
declare double @llvm.fmuladd.f64(double %a, double %b, double %c)
概要:

llvm.fmuladd.*’ 組み込み関数は、乗算と加算を組み合わせた式を表します。コードジェネレーターが、(a) 対象の命令セットが融合演算をサポートしており、かつ (b) 融合演算が等価な別々の乗算命令と加算命令のペアよりも効率的であると判断した場合に、融合演算が可能です。

引数:

llvm.fmuladd.*’ 組み込み関数はそれぞれ3つの引数を取ります。2つの被乗数 a と b、および被加数 c です。

意味:

%0 = call float @llvm.fmuladd.f32(%a, %b, %c)

は、a * b + c という式と同等ですが、乗算と加算のステップ間で丸めが実行されるかどうかは規定されていません。ターゲットプラットフォームが融合演算をサポートしていても、融合演算が保証されるわけではありません。融合された乗算-加算が必要な場合は、代わりに該当する llvm.fma 組み込み関数を使用する必要があります。これは ‘llvm.fma.*’ と同様に errno を設定することはありません。

例:
%r2 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) ; yields float:r2 = (a * b) + c

ハードウェアループ組み込み関数

LLVM は、ループをハードウェアループとしてマークするためのいくつかの組み込み関数をサポートしています。これらはバックエンドへのヒントであり、ターゲット固有の命令にさらに下げたり、ターゲット固有の制限が満たされずハードウェアループを生成できない場合は、ハードウェアループを通常のループに戻したりするために必要です。

これらの組み込み関数は将来変更される可能性があり、バックエンド以外で使用することを意図していません。したがって、フロントエンドおよびミッドレベルの最適化では、これらの組み込み関数を生成しないでください。

llvm.set.loop.iterations.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare void @llvm.set.loop.iterations.i32(i32)
declare void @llvm.set.loop.iterations.i64(i64)
概要:

llvm.set.loop.iterations.*’ 組み込み関数は、ハードウェアループのトリップ回数を指定するために使用されます。これらはループのプリヘッダー基本ブロックに配置され、オプティマイザーがこれらの命令を複製するのを避けるために IntrNoDuplicate としてマークされます。

引数:

整数オペランドはハードウェアループのトリップ回数であり、ループのバックエッジ実行回数などではありません。

意味:

llvm.set.loop.iterations.*’ 組み込み関数は、そのオペランドに対して算術演算を実行しません。これは、ターゲット固有の命令(通常はこの値を特殊なレジスタに移動したり、ハードウェアループ命令を実行したりする)を使用してハードウェアループカウントを設定するために使用できるバックエンドへのヒントです。

llvm.start.loop.iterations.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.start.loop.iterations.i32(i32)
declare i64 @llvm.start.loop.iterations.i64(i64)
概要:

llvm.start.loop.iterations.*’ 組み込み関数は、ハードウェアループのトリップ回数を指定するために使用される ‘llvm.set.loop.iterations.*’ 組み込み関数と似ていますが、ループへの入力として使用できる入力と同じ値を生成します。これらはループのプリヘッダー基本ブロックに配置され、出力はループの誘導変数の phi への入力であることが期待され、 ‘llvm.loop.decrement.reg.*’ によってデクリメントされます。

引数:

整数オペランドはハードウェアループのトリップ回数であり、ループのバックエッジ実行回数などではありません。

意味:

llvm.start.loop.iterations.*’ 組み込み関数は、そのオペランドに対して算術演算を実行しません。これは、ターゲット固有の命令(通常はこの値を特殊なレジスタに移動したり、ハードウェアループ命令を実行したりする)を使用してハードウェアループカウントを設定するために使用できるバックエンドへのヒントです。

llvm.test.set.loop.iterations.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i1 @llvm.test.set.loop.iterations.i32(i32)
declare i1 @llvm.test.set.loop.iterations.i64(i64)
概要:

llvm.test.set.loop.iterations.*’ 組み込み関数は、ループのトリップ回数を指定し、指定された回数がゼロでないことをテストするために使用され、while ループへの入力を制御することができます。これらはループのプリヘッダーの先行基本ブロックに配置され、オプティマイザーがこれらの命令を複製するのを避けるために IntrNoDuplicate としてマークされます。

引数:

整数オペランドはハードウェアループのトリップ回数であり、ループのバックエッジ実行回数などではありません。

意味:

llvm.test.set.loop.iterations.*’ 組み込み関数は、そのオペランドに対して算術演算を実行しません。これは、ターゲット固有の命令(通常はこの値を特殊なレジスタに移動したり、ハードウェアループ命令を実行したりする)を使用してハードウェアループカウントを設定するために使用できるバックエンドへのヒントです。結果は、指定された回数がゼロでないかどうかの条件付きの値です。

llvm.test.start.loop.iterations.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare {i32, i1} @llvm.test.start.loop.iterations.i32(i32)
declare {i64, i1} @llvm.test.start.loop.iterations.i64(i64)
概要:

llvm.test.start.loop.iterations.*’ 組み込み関数は、ハードウェアループのトリップ回数を指定するために使用される ‘llvm.test.set.loop.iterations.*’ および ‘llvm.start.loop.iterations.*’ 組み込み関数と似ていますが、ループへの入力として使用できる入力と同じ値を生成します。2 番目の i1 出力は while ループへの入力を制御します。

引数:

整数オペランドはハードウェアループのトリップ回数であり、ループのバックエッジ実行回数などではありません。

意味:

llvm.test.start.loop.iterations.*’ 組み込み関数は、そのオペランドに対して算術演算を実行しません。これは、ターゲット固有の命令(通常はこの値を特殊なレジスタに移動したり、ハードウェアループ命令を実行したりする)を使用してハードウェアループカウントを設定するために使用できるバックエンドへのヒントです。結果は、入力と、指定された回数がゼロでないかどうかの条件付きの値のペアです。

llvm.loop.decrement.reg.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.loop.decrement.reg.i32(i32, i32)
declare i64 @llvm.loop.decrement.reg.i64(i64, i64)
概要:

llvm.loop.decrement.reg.*’ 組み込み関数は、ループ反復カウンターを減らし、次のループテストチェックで使用される更新された値を返すために使用されます。

引数:

両方の引数は、同一の整数型である必要があります。最初のオペランドはループ反復カウンターです。2 番目のオペランドは、1 回の反復で処理される最大要素数です。

意味:

llvm.loop.decrement.reg.*’ 組み込み関数は、その 2 つのオペランドに対して整数 SUB を実行します。これはラップすることは許可されていません。これらは、まだ実行されるべき残りの反復回数を返し、 PHIICMP および BR とともに、実行されるループ反復回数を制御するために使用できます。任意の最適化は、これを SUB として扱うことが許可されており、SCEV によってサポートされているため、最適化される可能性がある場合はバックエンドの責任で処理する必要があります。これらの組み込み関数は、オプティマイザーがこれらの命令を複製するのを避けるために IntrNoDuplicate としてマークされます。

llvm.loop.decrement.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i1 @llvm.loop.decrement.i32(i32)
declare i1 @llvm.loop.decrement.i64(i64)
概要:

HardwareLoops パスを使用すると、ループの減分値をオプションで指定できます。デフォルトのループの減分値は 1 ですが、このオプションで指定された符号なし整数値を指定できます。‘llvm.loop.decrement.*’ 組み込み関数は、この値でループ反復カウンターを減らし、ループを終了する必要がある場合は false の述語を返し、それ以外の場合は true を返します。これは、ループカウンターが PHI ノードを介して更新されない場合に生成されます。これもオプションで制御できます。

引数:

整数引数は、ループ反復カウンターを減らすために使用されるループ減分値です。

意味:

llvm.loop.decrement.*’ 組み込み関数は、ループ反復カウンタを所定のループ減算値でSUB減算し、ループを終了すべき場合はfalseを返します。このSUB減算はラップ(オーバーフロー)することは許可されていません。結果は、ループを制御する条件付き分岐で使用される条件となります。

ベクトル削減組み込み関数

ベクトルの水平削減は、以下の組み込み関数を使用して表現できます。各関数は、ベクトルオペランドを入力として受け取り、ベクトルのすべての要素に対してそれぞれの演算を適用し、同じ要素型の単一のスカラー結果を返します。

llvm.vector.reduce.add.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
declare i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %a)
概要:

llvm.vector.reduce.add.*’ 組み込み関数は、ベクトルの整数ADD削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.fadd.*’ 組み込み関数

構文:
declare float @llvm.vector.reduce.fadd.v4f32(float %start_value, <4 x float> %a)
declare double @llvm.vector.reduce.fadd.v2f64(double %start_value, <2 x double> %a)
概要:

llvm.vector.reduce.fadd.*’ 組み込み関数は、ベクトルの浮動小数点ADD削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

組み込み関数呼び出しに 'reassoc' フラグが設定されている場合、削減は同等のスカラー化された対応物の結合性を保持しません。それ以外の場合、削減は*逐次的*になり、スカラー化された削減の結合性を尊重することを意味します。つまり、削減は開始値から始まり、連続して増加するベクトル要素インデックスを使用して fadd 演算を実行します。以下の疑似コードを参照してください。

float sequential_fadd(start_value, input_vector)
  result = start_value
  for i = 0 to length(input_vector)
    result = result + input_vector[i]
  return result
引数:

この組み込み関数の最初の引数は、削減の開始値となるスカラーです。開始値の型は、ベクトル入力の要素型と一致します。2 番目の引数は、浮動小数点値のベクトルである必要があります。

開始値を無視するには、浮動小数点加算のニュートラル値である負のゼロ (-0.0) を使用できます。

例:
%unord = call reassoc float @llvm.vector.reduce.fadd.v4f32(float -0.0, <4 x float> %input) ; relaxed reduction
%ord = call float @llvm.vector.reduce.fadd.v4f32(float %start_value, <4 x float> %input) ; sequential reduction

llvm.vector.reduce.mul.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %a)
declare i64 @llvm.vector.reduce.mul.v2i64(<2 x i64> %a)
概要:

llvm.vector.reduce.mul.*’ 組み込み関数は、ベクトルの整数MUL削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.fmul.*’ 組み込み関数

構文:
declare float @llvm.vector.reduce.fmul.v4f32(float %start_value, <4 x float> %a)
declare double @llvm.vector.reduce.fmul.v2f64(double %start_value, <2 x double> %a)
概要:

llvm.vector.reduce.fmul.*’ 組み込み関数は、ベクトルの浮動小数点MUL削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

組み込み関数呼び出しに 'reassoc' フラグが設定されている場合、削減は同等のスカラー化された対応物の結合性を保持しません。それ以外の場合、削減は*逐次的*になり、スカラー化された削減の結合性を尊重することを意味します。つまり、削減は開始値から始まり、連続して増加するベクトル要素インデックスを使用して fmul 演算を実行します。以下の疑似コードを参照してください。

float sequential_fmul(start_value, input_vector)
  result = start_value
  for i = 0 to length(input_vector)
    result = result * input_vector[i]
  return result
引数:

この組み込み関数の最初の引数は、削減の開始値となるスカラーです。開始値の型は、ベクトル入力の要素型と一致します。2 番目の引数は、浮動小数点値のベクトルである必要があります。

開始値を無視するには、浮動小数点乗算のニュートラル値である 1 (1.0) を使用できます。

例:
%unord = call reassoc float @llvm.vector.reduce.fmul.v4f32(float 1.0, <4 x float> %input) ; relaxed reduction
%ord = call float @llvm.vector.reduce.fmul.v4f32(float %start_value, <4 x float> %input) ; sequential reduction

llvm.vector.reduce.and.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.and.*’ 組み込み関数は、ベクトルのビット単位AND削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.or.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.or.*’ 組み込み関数は、ベクトルのビット単位OR削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.xor.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.xor.*’ 組み込み関数は、ベクトルのビット単位XOR削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.smax.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.smax.*’ 組み込み関数は、ベクトルの符号付き整数MAX削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.smin.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.smin.*’ 組み込み関数は、ベクトルの符号付き整数MIN削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.umax.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.umax.*’ 組み込み関数は、ベクトルの符号なし整数MAX削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.umin.*’ 組み込み関数

構文:
declare i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %a)
概要:

llvm.vector.reduce.umin.*’ 組み込み関数は、ベクトルの符号なし整数MIN削減を行い、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

引数:

この組み込み関数の引数は、整数のベクターである必要があります。

llvm.vector.reduce.fmax.*’ 組み込み関数

構文:
declare float @llvm.vector.reduce.fmax.v4f32(<4 x float> %a)
declare double @llvm.vector.reduce.fmax.v2f64(<2 x double> %a)
概要:

llvm.vector.reduce.fmax.*’ イントリンシックは、ベクトルの浮動小数点MAXリダクションを実行し、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

この命令は、‘llvm.maxnum.*’ イントリンシックと同じ比較セマンティクスを持ちます。つまり、ベクトルのすべての要素が NaN でない限り、結果は常に数値になります。最大要素の大きさが 0.0 で、+0.0 と -0.0 の両方の要素を含むベクトルの場合、結果の符号は不定です。

イントリンシック呼び出しに nnan 高速数学フラグがある場合、演算は入力ベクトルに NaN が存在しないと仮定できます。

引数:

このイントリンシックへの引数は、浮動小数点値のベクトルである必要があります。

llvm.vector.reduce.fmin.*’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vector.reduce.fmin.v4f32(<4 x float> %a)
declare double @llvm.vector.reduce.fmin.v2f64(<2 x double> %a)
概要:

llvm.vector.reduce.fmin.*’ イントリンシックは、ベクトルの浮動小数点MINリダクションを実行し、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

この命令は、‘llvm.minnum.*’ イントリンシックと同じ比較セマンティクスを持ちます。つまり、ベクトルのすべての要素が NaN でない限り、結果は常に数値になります。最小要素の大きさが 0.0 で、+0.0 と -0.0 の両方の要素を含むベクトルの場合、結果の符号は不定です。

イントリンシック呼び出しに nnan 高速数学フラグがある場合、演算は入力ベクトルに NaN が存在しないと仮定できます。

引数:

このイントリンシックへの引数は、浮動小数点値のベクトルである必要があります。

llvm.vector.reduce.fmaximum.*’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> %a)
declare double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> %a)
概要:

llvm.vector.reduce.fmaximum.*’ イントリンシックは、ベクトルの浮動小数点MAXリダクションを実行し、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

この命令は、‘llvm.maximum.*’ イントリンシックと同じ比較セマンティクスを持ちます。つまり、このイントリンシックは NaN を伝播し、+0.0 は -0.0 より大きいと見なされます。ベクトルのいずれかの要素が NaN の場合、結果は NaN になります。

引数:

このイントリンシックへの引数は、浮動小数点値のベクトルである必要があります。

llvm.vector.reduce.fminimum.*’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vector.reduce.fminimum.v4f32(<4 x float> %a)
declare double @llvm.vector.reduce.fminimum.v2f64(<2 x double> %a)
概要:

llvm.vector.reduce.fminimum.*’ イントリンシックは、ベクトルの浮動小数点MINリダクションを実行し、結果をスカラーとして返します。戻り値の型は、ベクトル入力の要素型と一致します。

この命令は、‘llvm.minimum.*’ イントリンシックと同じ比較セマンティクスを持ちます。つまり、このイントリンシックは NaN を伝播し、-0.0 は +0.0 より小さいと見なされます。ベクトルのいずれかの要素が NaN の場合、結果は NaN になります。

引数:

このイントリンシックへの引数は、浮動小数点値のベクトルである必要があります。

llvm.vector.insert’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

; Insert fixed type into scalable type
declare <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v4f32(<vscale x 4 x float> %vec, <4 x float> %subvec, i64 <idx>)
declare <vscale x 2 x double> @llvm.vector.insert.nxv2f64.v2f64(<vscale x 2 x double> %vec, <2 x double> %subvec, i64 <idx>)

; Insert scalable type into scalable type
declare <vscale x 4 x float> @llvm.vector.insert.nxv4f64.nxv2f64(<vscale x 4 x float> %vec, <vscale x 2 x float> %subvec, i64 <idx>)

; Insert fixed type into fixed type
declare <4 x double> @llvm.vector.insert.v4f64.v2f64(<4 x double> %vec, <2 x double> %subvec, i64 <idx>)
概要:

llvm.vector.insert.*’ イントリンシックは、指定されたインデックスから始まる別のベクトルにベクトルを挿入します。戻り値の型は、挿入先のベクトルの型と一致します。概念的には、これはスケーラブルでないベクトルからスケーラブルなベクトルを構築するために使用できますが、このイントリンシックは純粋な固定型にも使用できます。

スケーラブルなベクトルは、他のスケーラブルなベクトルにのみ挿入できます。

引数:

vec は、subvec が挿入されるベクトルです。subvec は、挿入されるベクトルです。

idx は、subvec が挿入される開始要素番号を表します。idx は、subvec の既知の最小ベクトル長の定数倍である必要があります。subvec がスケーラブルなベクトルの場合、idx は最初に subvec のランタイムスケーリング係数でスケーリングされます。idx から始まる vec の要素は、subvec で上書きされます。idx から (idx + num_elements(subvec) - 1) までの要素は、有効な vec インデックスである必要があります。この条件を静的に判断できないが、実行時に false の場合、結果のベクトルはpoison 値になります。

llvm.vector.extract’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

; Extract fixed type from scalable type
declare <4 x float> @llvm.vector.extract.v4f32.nxv4f32(<vscale x 4 x float> %vec, i64 <idx>)
declare <2 x double> @llvm.vector.extract.v2f64.nxv2f64(<vscale x 2 x double> %vec, i64 <idx>)

; Extract scalable type from scalable type
declare <vscale x 2 x float> @llvm.vector.extract.nxv2f32.nxv4f32(<vscale x 4 x float> %vec, i64 <idx>)

; Extract fixed type from fixed type
declare <2 x double> @llvm.vector.extract.v2f64.v4f64(<4 x double> %vec, i64 <idx>)
概要:

llvm.vector.extract.*’ イントリンシックは、指定されたインデックスから始まる別のベクトル内からベクトルを抽出します。戻り値の型は明示的に指定する必要があります。概念的には、これはスケーラブルなベクトルをスケーラブルでない部分に分解するために使用できますが、このイントリンシックは純粋な固定型にも使用できます。

スケーラブルなベクトルは、他のスケーラブルなベクトルからのみ抽出できます。

引数:

vec は、サブベクトルを抽出するベクトルです。

idx は、vec 内のサブベクトルが抽出される開始要素番号を指定します。idx は、結果型の既知の最小ベクトル長の定数倍である必要があります。結果型がスケーラブルなベクトルの場合、idx は最初に結果型のランタイムスケーリング係数でスケーリングされます。idx から (idx + num_elements(result_type) - 1) までの要素は、有効なベクトルインデックスである必要があります。この条件を静的に判断できないが、実行時に false の場合、結果のベクトルはpoison 値になります。idx パラメータは、ベクトルインデックス定数型である必要があります (ほとんどのターゲットでは、これは整数ポインタ型になります)。

llvm.vector.reverse’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare <2 x i8> @llvm.vector.reverse.v2i8(<2 x i8> %a)
declare <vscale x 4 x i32> @llvm.vector.reverse.nxv4i32(<vscale x 4 x i32> %a)
概要:

llvm.vector.reverse.*’ イントリンシックは、ベクトルを反転します。このイントリンシックは、単一のベクトルを受け取り、元のレーン順序が反転した一致する型のベクトルを返します。これらのイントリンシックは、固定ベクトルとスケーラブルなベクトルの両方で機能します。このイントリンシックはすべてのベクトル型をサポートしていますが、固定幅ベクトルのこの演算を表現する推奨方法は、シャッフルベクトルを使用することです。これにより、より多くの最適化の機会が得られる可能性があります。

引数:

このイントリンシックへの引数は、ベクトルである必要があります。

llvm.vector.deinterleave2’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare {<2 x double>, <2 x double>} @llvm.vector.deinterleave2.v4f64(<4 x double> %vec1)
declare {<vscale x 4 x i32>, <vscale x 4 x i32>}  @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %vec1)
概要:

llvm.vector.deinterleave2’ イントリンシックは、入力ベクトルの偶数レーンと奇数レーンをデインターリーブすることにより、2 つのベクトルを構築します。

このイントリンシックは、固定ベクトルとスケーラブルなベクトルの両方で機能します。このイントリンシックはすべてのベクトル型をサポートしていますが、固定幅ベクトルのこの演算を表現する推奨方法は、シャッフルベクトルを使用することです。これにより、より多くの最適化の機会が得られる可能性があります。

例:

{<2 x i64>, <2 x i64>} llvm.vector.deinterleave2.v4i64(<4 x i64> <i64 0, i64 1, i64 2, i64 3>); ==> {<2 x i64> <i64 0, i64 2>, <2 x i64> <i64 1, i64 3>}
引数:

引数は、2 つの結果型の論理的な連結に対応する型のベクトルです。

llvm.vector.interleave2’ イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x double> @llvm.vector.interleave2.v4f64(<2 x double> %vec1, <2 x double> %vec2)
declare <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %vec1, <vscale x 4 x i32> %vec2)
概要:

llvm.vector.interleave2’ イントリンシックは、2 つの入力ベクトルをインターリーブすることにより、ベクトルを構築します。

このイントリンシックは、固定ベクトルとスケーラブルなベクトルの両方で機能します。このイントリンシックはすべてのベクトル型をサポートしていますが、固定幅ベクトルのこの演算を表現する推奨方法は、シャッフルベクトルを使用することです。これにより、より多くの最適化の機会が得られる可能性があります。

例:

<4 x i64> llvm.vector.interleave2.v4i64(<2 x i64> <i64 0, i64 2>, <2 x i64> <i64 1, i64 3>); ==> <4 x i64> <i64 0, i64 1, i64 2, i64 3>
引数:

両方の引数は、その論理的な連結が結果の型と一致する同じ型のベクトルである必要があります。

llvm.experimental.cttz.elts’ イントリンシック

構文:

これはオーバーロードされたイントリンシックです。固定幅とスケーラブルの両方の整数要素の任意のベクトルで、`llvm.experimental.cttz.elts` を使用できます。

declare i8 @llvm.experimental.cttz.elts.i8.v8i1(<8 x i1> <src>, i1 <is_zero_poison>)
概要:

llvm.experimental.cttz.elts’ イントリンシックは、ベクトルの末尾のゼロ要素の数をカウントします。

引数:

最初の引数は、カウントされるベクターです。この引数は、整数要素型を持つベクターでなければなりません。戻り値の型も、ソースベクターの最大要素数を保持するのに十分な幅を持つ整数型でなければなりません。戻り値の型が入力ベクターの要素数に対して十分な幅を持たない場合、この組み込み関数の動作は未定義です。

2番目の引数は、最初の引数がすべてゼロの場合に、組み込み関数が有効な結果を返すかどうかを示す定数フラグです。最初の引数がすべてゼロで、2番目の引数がtrueの場合、結果はポイズン値になります。

意味:

llvm.experimental.cttz.elts’ 組み込み関数は、ベクター内の末尾(最下位)のゼロ要素をカウントします。src == 0 の場合、結果は入力ベクターの要素数になります。

llvm.vector.splice’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <2 x double> @llvm.vector.splice.v2f64(<2 x double> %vec1, <2 x double> %vec2, i32 %imm)
declare <vscale x 4 x i32> @llvm.vector.splice.nxv4i32(<vscale x 4 x i32> %vec1, <vscale x 4 x i32> %vec2, i32 %imm)
概要:

llvm.vector.splice.*’ 組み込み関数は、最初の入力ベクターの要素と2番目の入力ベクターの要素を連結してベクターを構築し、入力ベクターと同じ型のベクターを返します。符号付き即値は、ベクター内の要素数で割った余りを計算し、結果の値を取り出す開始インデックスを最初のベクターに対して決定します。これは、概念的には、正の即値の場合、concat(%vec1, %vec2) からインデックス imm で始まるベクターが抽出されることを意味し、負の即値の場合、最初のベクターから -imm 個の末尾要素が抽出され、残りの要素は %vec2 から抽出されることを意味します。

これらの組み込み関数は、固定およびスケーラブルなベクターの両方で機能します。この組み込み関数はすべてのベクター型をサポートしますが、固定幅ベクターに対してこの操作を表現する推奨方法は、より多くの最適化機会を可能にする可能性がある shufflevector を使用することです。

例:

llvm.vector.splice(<A,B,C,D>, <E,F,G,H>, 1);  ==> <B, C, D, E> index
llvm.vector.splice(<A,B,C,D>, <E,F,G,H>, -3); ==> <B, C, D, E> trailing elements
引数:

最初の2つのオペランドは、同じ型のベクターです。開始インデックスは、ソースベクターの実行時の要素数で割った余りである imm です。固定幅ベクター <N x eltty> の場合、imm は -N <= imm < N の範囲の符号付き整数定数です。スケーラブルベクター <vscale x N x eltty> の場合、imm は -X <= imm < X の範囲の符号付き整数定数です。ここで、X = vscale_range_min * N です。

llvm.stepvector’ 組み込み関数

これはオーバーロードされた組み込み関数です。llvm.stepvector を使用して、レーン値が線形シーケンス <0, 1, 2, …> で構成されるベクターを生成できます。これは主にスケーラブルベクターを対象としています。

declare <vscale x 4 x i32> @llvm.stepvector.nxv4i32()
declare <vscale x 8 x i16> @llvm.stepvector.nxv8i16()

llvm.stepvector’ 組み込み関数は、0 から始まり 1 ずつ増加する値の線形シーケンスを含む整数のベクターを作成するために使用されます。この組み込み関数は、サイズが少なくとも 8 ビットの整数要素を持つベクターにのみ使用できます。シーケンス値が要素型で許可されている制限を超えた場合、そのレーンの結果はポイズン値になります。

これらの組み込み関数は、固定およびスケーラブルなベクターの両方で機能します。この組み込み関数はすべてのベクター型をサポートしますが、固定幅ベクターに対してこの操作を表現する推奨方法は、代わりに定数ベクターを生成することです。

引数:

なし。

llvm.experimental.get.vector.length’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.experimental.get.vector.length.i32(i32 %cnt, i32 immarg %vf, i1 immarg %scalable)
declare i32 @llvm.experimental.get.vector.length.i64(i64 %cnt, i32 immarg %vf, i1 immarg %scalable)
概要:

llvm.experimental.get.vector.length.*’ 組み込み関数は、処理する要素数を取り、要求されたベクトライゼーション係数で処理できる要素数を返します。

引数:

最初の引数は、任意のスカラ整数型の符号なし値であり、処理する要素の合計数を指定します。2番目の引数は、ベクトライゼーション係数の i32 即値です。3番目の引数は、ベクトライゼーション係数に vscale を掛ける必要があるかどうかを示します。

意味:

コンパイル時には不明でハードウェア仕様に依存する、負でない i32 値(明示的なベクター長)を返します。結果の値が結果の型に収まらない場合、結果はポイズン値になります。

この組み込み関数は、ループ反復ごとに処理する要素数を取得するために、VP 組み込み関数を使用したループベクトライゼーションで使用することを目的としています。結果は、カウントがゼロになるまで、次の反復のカウントを減らすために使用する必要があります。

%max_lanes%vf および %scalable で記述された型のレーン数とします。返される値の制約は次のとおりです。

  • %cnt が 0 に等しい場合、0 を返します。

  • 返される値は常に %max_lanes 以下です。

  • %cnt がゼロでない場合、返される値は常に ceil(%cnt / ceil(%cnt / %max_lanes)) 以上です。

  • 返される値は、各ループ反復で単調に減少します。つまり、反復で返される値は、後の反復の値以上です。

これには次の意味があることに注意してください。

  • この組み込み関数を使用するループの場合、反復回数は ceil(%C / %max_lanes) に等しくなります。ここで、%C は初期 %cnt 値です。

  • %cnt がゼロでない場合、戻り値もゼロではありません。

  • %cnt%max_lanes 以下の場合、戻り値は %cnt に等しくなります。

llvm.experimental.vector.partial.reduce.add.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x i32> @llvm.experimental.vector.partial.reduce.add.v4i32.v4i32.v8i32(<4 x i32> %a, <8 x i32> %b)
declare <4 x i32> @llvm.experimental.vector.partial.reduce.add.v4i32.v4i32.v16i32(<4 x i32> %a, <16 x i32> %b)
declare <vscale x 4 x i32> @llvm.experimental.vector.partial.reduce.add.nxv4i32.nxv4i32.nxv8i32(<vscale x 4 x i32> %a, <vscale x 8 x i32> %b)
declare <vscale x 4 x i32> @llvm.experimental.vector.partial.reduce.add.nxv4i32.nxv4i32.nxv16i32(<vscale x 4 x i32> %a, <vscale x 16 x i32> %b)
概要:

llvm.vector.experimental.partial.reduce.add.*’ 組み込み関数は、2つのベクターオペランドの連結を、結果の型によって指示された要素数まで縮小します。結果の型は、最初のオペランドベクターの型と一致するベクター型です。

引数:

両方の引数は、一致する要素型のベクターである必要があります。最初の引数の型は結果の型と一致する必要があり、2番目の引数の型は、最初のベクター/結果の型の正の整数倍であるベクター長を持つ必要があります。引数は、固定ベクターまたはスケーラブルベクターの両方である必要があります。

llvm.experimental.vector.histogram.*’ 組み込み関数

これらの組み込み関数はオーバーロードされています。

これらの組み込み関数は、ヒストグラムのような操作、つまり、連続していない可能性のあるメモリ内の値を更新する操作を表します。また、単一のベクター内の複数の要素がメモリ内の同じ値を更新する可能性があります。

更新操作は、組み込み関数名の一部として指定する必要があります。次の単純なヒストグラムのように、add 操作が使用されます。

void simple_histogram(int *restrict buckets, unsigned *indices, int N, int inc) {
  for (int i = 0; i < N; ++i)
    buckets[indices[i]] += inc;
}

今後、より多くの更新操作タイプが追加される可能性があります。

declare <8 x i32> @llvm.experimental.vector.histogram.add.v8p0.i32(<8 x ptr> %ptrs, i32 %inc, <8 x i1> %mask)
declare <vscale x 2 x i64> @llvm.experimental.vector.histogram.add.nxv2p0.i64(<vscale x 2 x ptr> %ptrs, i64 %inc, <vscale x 2 x i1> %mask)
引数:

最初の引数は、更新されるメモリロケーションへのポインターのベクターです。2番目の引数は、メモリから値を更新するために使用されるスカラです。これは、更新される値の型と一致する必要があります。最後の引数は、変更されないロケーションを除外するためのマスク値です。

意味:

llvm.experimental.vector.histogram.*’ 組み込み関数は、メモリ内の潜在的に重複する値に対して更新を実行するために使用されます。これらの組み込み関数は、次の操作シーケンスを表します。

  1. ptrs オペランドから、inc オペランドの型と一致する要素型でロードを収集します。

  2. メモリからロードされた値の更新。add 更新操作の場合、これは次のことを意味します。

    1. ptrs オペランドに対してクロスベクターヒストグラム操作を実行します。

    2. 結果に inc オペランドを掛けます。

    3. 結果をメモリからロードされた値に追加します。

  3. 更新操作の結果を、ptrs オペランドのメモリロケーションに散乱します。

mask オペランドは、少なくとも gather および scatter 操作に適用されます。

llvm.experimental.vector.compress.*」イントリンシック

LLVM は、選択マスクに基づいてベクトル内のデータを圧縮するためのイントリンシックを提供します。意味的には、これは llvm.masked.compressstore と似ていますが、前提条件が弱く、結果をメモリに格納しない、つまりデータはベクトル内に残ります。

構文:

これはオーバーロードされたイントリンシックです。整数、浮動小数点、またはポインタデータ型の多数のスカラー値が入力ベクトルから収集され、結果ベクトル内で隣接して配置されます。マスクは、ベクトルから収集する要素を定義します。残りのレーンは、passthru からの値で埋められます。

declare <8 x i32> @llvm.experimental.vector.compress.v8i32(<8 x i32> <value>, <8 x i1> <mask>, <8 x i32> <passthru>)
declare <16 x float> @llvm.experimental.vector.compress.v16f32(<16 x float> <value>, <16 x i1> <mask>, <16 x float> undef)
概要:

入力ベクトル value から mask に従って要素を選択します。選択されたすべての要素は、結果ベクトルの隣接するレーンに、小さい方から大きい方へ書き込まれます。マスクは各ベクトルのレーンに対してエントリを保持し、保持する要素を選択するために使用されます。passthru ベクトルが指定されている場合、残りのすべてのレーンは passthru から対応するレーンの値で埋められます。llvm.masked.compressstore との主な違いは、選択されていないレーンに対するメモリアクセスをガードする必要がないことです。これにより、llvm.masked.compressstore の明示的なセマンティクスをサポートしていない、または非効率的な命令しか持たないが、何らかの形式の圧縮操作を持つすべてのターゲットに対して、分岐のないコードとより良い最適化が可能になります。結果ベクトルは、選択されたすべての値がベクトルの低い位置にあるため、同様の効果で書き込むことができますが、マスクが false の場合に書き込みを避けるために分岐する必要はありません。

引数:

最初のオペランドは、要素が選択される入力ベクトルです。2 番目のオペランドは、ブール値のベクトルのマスクです。3 番目のオペランドは、残りのレーンに要素が埋められる passthru ベクトルです。マスクと入力ベクトルは、同じ数のベクトル要素を持っている必要があります。入力ベクトルと passthru ベクトルは、同じ型を持っている必要があります。

セマンティクス:

llvm.experimental.vector.compress イントリンシックは、ベクトル内のデータを圧縮します。ベクトルの隣接していない可能性のあるレーンから要素を収集し、選択マスクに基づいて結果ベクトルに連続して配置し、残りのレーンを passthru からの値で埋めます。このイントリンシックは、次の C++ の例のロジックを実行します。passthru が未定義の場合、最後に選択された後の out 内のすべての値は未定義です。mask 内のすべてのエントリが 0 の場合、out ベクトルは passthru です。マスクのいずれかの要素が poison の場合、結果のすべての要素は poison です。それ以外の場合、マスクのいずれかの要素が undef の場合、結果のすべての要素は undef です。passthru が未定義の場合、有効なレーンの数は、マスク内の true エントリの数と等しくなります。つまり、すべてのレーン >= 選択された値の数は未定義です。

// Consecutively place selected values in a vector.
using VecT __attribute__((vector_size(N))) = int;
VecT compress(VecT vec, VecT mask, VecT passthru) {
  VecT out;
  int idx = 0;
  for (int i = 0; i < N / sizeof(int); ++i) {
    out[idx] = vec[i];
    idx += static_cast<bool>(mask[i]);
  }
  for (; idx < N / sizeof(int); ++idx) {
    out[idx] = passthru[idx];
  }
  return out;
}

行列イントリンシック

(行/列の数やメモリレイアウトなど) 形状情報が必要な行列に対する操作は、行列イントリンシックを使用して表現できます。これらのイントリンシックでは、行列の次元を即時引数として渡す必要があり、行列はベクトルとして渡され、返されます。つまり、R x C 行列の場合、列 j の要素 i は、対応するベクトルではインデックス j * R + i にあり、インデックスは 0 から始まります。現在、列優先レイアウトが想定されています。イントリンシックは、整数行列と浮動小数点行列の両方をサポートします。

llvm.matrix.transpose.*」イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare vectorty @llvm.matrix.transpose.*(vectorty %In, i32 <Rows>, i32 <Cols>)
概要:

llvm.matrix.transpose.*」イントリンシックは、%In<Rows> x <Cols> 行列として扱い、結果ベクトルに転置された行列を返します。

引数:

最初の引数 %In は、<Rows> x <Cols> 行列に対応するベクトルです。したがって、引数 <Rows><Cols> は、それぞれ行数と列数に対応し、正の定数整数である必要があります。返されるベクトルは、<Rows> * <Cols> 個の要素を持ち、%In と同じ浮動小数点または整数要素型を持っている必要があります。

llvm.matrix.multiply.*」イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare vectorty @llvm.matrix.multiply.*(vectorty %A, vectorty %B, i32 <OuterRows>, i32 <Inner>, i32 <OuterColumns>)
概要:

llvm.matrix.multiply.*」イントリンシックは、%A<OuterRows> x <Inner> 行列、%B<Inner> x <OuterColumns> 行列として扱い、それらを乗算します。結果行列は、結果ベクトルで返されます。

引数:

最初のベクトル引数 %A<OuterRows> * <Inner> 個の要素を持つ行列に対応し、2 番目の引数 %B<Inner> * <OuterColumns> 個の要素を持つ行列に対応します。引数 <OuterRows><Inner>、および <OuterColumns> は、正の定数整数である必要があります。返されるベクトルは、<OuterRows> * <OuterColumns> 個の要素を持っている必要があります。ベクトル %A%B、および返されるベクトルはすべて、同じ浮動小数点または整数要素型を持っています。

llvm.matrix.column.major.load.*」イントリンシック

構文:

これはオーバーロードされた組み込み関数です。

declare vectorty @llvm.matrix.column.major.load.*(
    ptrty %Ptr, i64 %Stride, i1 <IsVolatile>, i32 <Rows>, i32 <Cols>)
概要:

llvm.matrix.column.major.load.*」イントリンシックは、異なる列の開始アドレスを計算するために %Stride のストライドを使用して、<Rows> x <Cols> 行列をロードします。オフセットは %Stride のビット幅を使用して計算されます。これにより、部分行列の便利なロードが可能になります。<IsVolatile> が true の場合、イントリンシックは揮発性メモリアクセスとみなされます。結果行列は、結果ベクトルで返されます。%Ptr 引数が何らかの境界にアラインされていることがわかっている場合は、引数の属性として指定できます。

引数:

最初の引数 %Ptr は、返されたベクトルの型へのポインタ型であり、ロード元の開始アドレスに対応します。2 番目の引数 %Stride は、%Stride >= <Rows> を持つ正の定数整数です。%Stride は、列のメモリアドレスを計算するために使用されます。つまり、列 C の場合、その開始メモリアドレスは %Ptr + C * %Stride で計算されます。3 番目の引数 <IsVolatile> は、ブール値です。4 番目と 5 番目の引数である <Rows><Cols> は、それぞれ行数と列数に対応し、正の定数整数である必要があります。返されるベクトルは、<Rows> * <Cols> 個の要素を持っている必要があります。

%Ptr 引数には、align パラメータ属性を指定できます。

llvm.matrix.column.major.store.*’ 組み込み関数

構文:
declare void @llvm.matrix.column.major.store.*(
    vectorty %In, ptrty %Ptr, i64 %Stride, i1 <IsVolatile>, i32 <Rows>, i32 <Cols>)
概要:

llvm.matrix.column.major.store.*’ 組み込み関数は、%In 内の <Rows> x <Cols> 行列を、列間のストライド %Stride を使用してメモリに格納します。オフセットは、%Stride のビット幅を使用して計算されます。<IsVolatile> が true の場合、組み込み関数は 揮発性メモリアクセス とみなされます。

%Ptr 引数が特定の境界にアラインされていることがわかっている場合、引数に属性として指定できます。

引数:

最初の引数 %In は、メモリに格納される <Rows> x <Cols> 行列に対応するベクトルです。2 番目の引数 %Ptr は、%In のベクトル型のポインタであり、メモリ内の行列の開始アドレスです。3 番目の引数 %Stride は、%Stride >= <Rows> の正の定数整数です。%Stride は、列のメモリアドレスを計算するために使用されます。つまり、列 C の場合、その開始メモリアドレスは %Ptr + C * %Stride で計算されます。4 番目の引数 <IsVolatile> はブール値です。引数 <Rows> および <Cols> は、それぞれ行数と列数に対応し、正の定数整数である必要があります。

%Ptr 引数には、align パラメータ属性を指定できます。

半精度浮動小数点組み込み関数

ほとんどのターゲットプラットフォームでは、半精度浮動小数点数はストレージ専用の形式です。つまり、メモリ内では密なエンコーディングですが、その形式での計算はサポートされていません。

つまり、コードは最初に半精度浮動小数点値を i16 としてロードし、次に llvm.convert.from.fp16 を使用して float に変換する必要があります。その後、float 値に対して計算を実行できます (double などへの拡張を含む)。値をメモリに格納するには、必要に応じて最初に float に変換し、次に llvm.convert.to.fp16 を使用して i16 に変換し、i16 値として格納します。

llvm.convert.to.fp16’ 組み込み関数

構文:
declare i16 @llvm.convert.to.fp16.f32(float %a)
declare i16 @llvm.convert.to.fp16.f64(double %a)
概要:

llvm.convert.to.fp16’ 組み込み関数は、従来の浮動小数点型から半精度浮動小数点形式への変換を実行します。

引数:

この組み込み関数には、変換される単一の値の引数が含まれています。

セマンティクス:

llvm.convert.to.fp16’ 組み込み関数は、従来の浮動小数点形式から半精度浮動小数点形式への変換を実行します。戻り値は、変換された数値を含む i16 です。

例:
%res = call i16 @llvm.convert.to.fp16.f32(float %a)
store i16 %res, i16* @x, align 2

llvm.convert.from.fp16’ 組み込み関数

構文:
declare float @llvm.convert.from.fp16.f32(i16 %a)
declare double @llvm.convert.from.fp16.f64(i16 %a)
概要:

llvm.convert.from.fp16’ 組み込み関数は、半精度浮動小数点形式から単精度浮動小数点形式への変換を実行します。

引数:

この組み込み関数には、変換される単一の値の引数が含まれています。

セマンティクス:

llvm.convert.from.fp16’ 組み込み関数は、半精度浮動小数点形式から単精度浮動小数点形式への変換を実行します。入力の半精度浮動小数点値は、i16 値で表されます。

例:
%a = load i16, ptr @x, align 2
%res = call float @llvm.convert.from.fp16(i16 %a)

浮動小数点から整数への飽和変換

fptoui および fptosi 命令は、ゼロに向かって丸められた値が結果の型で表現できない場合、poison value を返します。これらの組み込み関数は、代わりに表現可能な最小および最大の整数値に向かって飽和する代替変換を提供します。

llvm.fptoui.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点引数型と任意の整数結果型、またはそれらのベクトルで llvm.fptoui.sat を使用できます。ただし、すべてのターゲットがすべての型をサポートしているとは限りません。

declare i32 @llvm.fptoui.sat.i32.f32(float %f)
declare i19 @llvm.fptoui.sat.i19.f64(double %f)
declare <4 x i100> @llvm.fptoui.sat.v4i100.v4f128(<4 x fp128> %f)
概要:

この組み込み関数は、飽和セマンティクスを使用して引数を符号なし整数に変換します。

引数:

引数は、任意の浮動小数点型または浮動小数点型のベクトルにすることができます。戻り値は、任意の整数型または整数型のベクトルにすることができます。引数と戻り値のベクトルの要素数は同じである必要があります。

セマンティクス:

整数への変換は、次の規則に従って実行されます

  • 引数が NaN の場合、ゼロが返されます。

  • 引数がゼロより小さい場合 (負の無限大を含む)、ゼロが返されます。

  • 引数が結果型の表現可能な最大の符号なし整数よりも大きい場合 (正の無限大を含む)、表現可能な最大の符号なし整数が返されます。

  • それ以外の場合は、引数をゼロに向かって丸めた結果が返されます。

例:
%a = call i8 @llvm.fptoui.sat.i8.f32(float 123.9)              ; yields i8: 123
%b = call i8 @llvm.fptoui.sat.i8.f32(float -5.7)               ; yields i8:   0
%c = call i8 @llvm.fptoui.sat.i8.f32(float 377.0)              ; yields i8: 255
%d = call i8 @llvm.fptoui.sat.i8.f32(float 0xFFF8000000000000) ; yields i8:   0

llvm.fptosi.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の浮動小数点引数型と任意の整数結果型、またはそれらのベクトルで llvm.fptosi.sat を使用できます。ただし、すべてのターゲットがすべての型をサポートしているとは限りません。

declare i32 @llvm.fptosi.sat.i32.f32(float %f)
declare i19 @llvm.fptosi.sat.i19.f64(double %f)
declare <4 x i100> @llvm.fptosi.sat.v4i100.v4f128(<4 x fp128> %f)
概要:

この組み込み関数は、飽和セマンティクスを使用して引数を符号付き整数に変換します。

引数:

引数は、任意の浮動小数点型または浮動小数点型のベクトルにすることができます。戻り値は、任意の整数型または整数型のベクトルにすることができます。引数と戻り値のベクトルの要素数は同じである必要があります。

セマンティクス:

整数への変換は、次の規則に従って実行されます

  • 引数が NaN の場合、ゼロが返されます。

  • 引数が結果型の表現可能な最小の符号付き整数よりも小さい場合 (負の無限大を含む)、表現可能な最小の符号付き整数が返されます。

  • 引数が結果型の表現可能な最大の符号付き整数よりも大きい場合 (正の無限大を含む)、表現可能な最大の符号付き整数が返されます。

  • それ以外の場合は、引数をゼロに向かって丸めた結果が返されます。

例:
%a = call i8 @llvm.fptosi.sat.i8.f32(float 23.9)               ; yields i8:   23
%b = call i8 @llvm.fptosi.sat.i8.f32(float -130.8)             ; yields i8: -128
%c = call i8 @llvm.fptosi.sat.i8.f32(float 999.0)              ; yields i8:  127
%d = call i8 @llvm.fptosi.sat.i8.f32(float 0xFFF8000000000000) ; yields i8:    0

収束組み込み関数

convergent 操作のセマンティクスを制御するための LLVM 収束組み込み関数 (すべて llvm.experimental.convergence. プレフィックスで始まる) については、収束演算セマンティクス ドキュメントで説明します。

デバッガー組み込み関数

LLVM デバッガー組み込み関数 (すべて llvm.dbg. プレフィックスで始まる) については、LLVM ソースレベルデバッグ ドキュメントで説明します。

例外処理組み込み関数

LLVM 例外処理組み込み関数 (すべて llvm.eh. プレフィックスで始まる) については、LLVM 例外処理 ドキュメントで説明します。

ポインタ認証組み込み関数

LLVMのポインタ認証組み込み関数(すべてllvm.ptrauth.という接頭辞で始まる)は、ポインタ認証ドキュメントで説明されています。

トランポリン組み込み関数

これらの組み込み関数を使用すると、nest属性でマークされた1つのパラメーターを関数から削除できます。その結果、ネストパラメーターのない呼び出し可能な関数ポインターが得られます。呼び出し側は、その値を提供する必要はありません。代わりに、使用する値は、通常スタックに割り当てられるメモリブロックである「トランポリン」に事前に格納されます。このトランポリンには、ネスト値を引数リストにスプライスするコードも含まれています。これは、GCCのネストされた関数アドレス拡張を実装するために使用されます。

たとえば、関数がi32 f(ptr nest %c, i32 %x, i32 %y)である場合、結果の関数ポインターはi32 (i32, i32)というシグネチャを持ちます。これは次のように作成できます。

%tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
call ptr @llvm.init.trampoline(ptr %tramp, ptr @f, ptr %nval)
%fp = call ptr @llvm.adjust.trampoline(ptr %tramp)

呼び出し%val = call i32 %fp(i32 %x, i32 %y)は、%val = call i32 %f(ptr %nval, i32 %x, i32 %y)と同等です。

llvm.init.trampoline’ 組み込み関数

構文:
declare void @llvm.init.trampoline(ptr <tramp>, ptr <func>, ptr <nval>)
概要:

これは、trampが指すメモリを実行可能コードで埋め、トランポリンに変換します。

引数:

llvm.init.trampoline組み込み関数は、3つの引数(すべてポインター)を取ります。tramp引数は、十分な大きさで十分なアライメントを持つメモリブロックを指している必要があります。このメモリは、組み込み関数によって書き込まれます。サイズとアライメントはターゲット固有であることに注意してください。LLVMは現在、それらを決定する移植可能な方法を提供していないため、この組み込み関数を生成するフロントエンドは、ターゲット固有の知識を持っている必要があります。func引数は、関数を保持する必要があります。

セマンティクス:

trampが指すメモリブロックは、ターゲット依存のコードで埋められ、関数に変換されます。次に、trampllvm.adjust.trampolineに渡して、(新しい関数に)ビットキャストして呼び出すことができるポインターを取得する必要があります。新しい関数のシグネチャは、nest属性でマークされた引数が削除されたfuncのシグネチャと同じです。このようなnest引数は最大1つしか許可されておらず、ポインター型である必要があります。新しい関数を呼び出すことは、同じ引数リストでfuncを呼び出すことと同じですが、不足しているnest引数にはnvalが使用されます。llvm.init.trampolineを呼び出した後、trampが指すメモリが変更された場合、後で返された関数ポインターを呼び出すことの効果は未定義です。

llvm.adjust.trampoline’ 組み込み関数

構文:
declare ptr @llvm.adjust.trampoline(ptr <tramp>)
概要:

これは、トランポリンのアドレス(trampとして渡される)に必要なマシン固有の調整を実行します。

引数:

trampは、以前にllvm.init.trampolineの呼び出しによってトランポリンコードが埋め込まれたメモリブロックを指している必要があります。

セマンティクス:

一部のアーキテクチャでは、実行されるコードのアドレスは、トランポリンが実際に格納されているアドレスとは異なる必要があります。この組み込み関数は、必要なマシン固有の調整を実行した後、trampに対応する実行可能アドレスを返します。返されたポインターは、ビットキャストして実行できます。

ベクター述語組み込み関数

VP組み込み関数は、述語付きSIMD/ベクターコードを対象としています。典型的なVP操作は、次のように、ベクターマスクと明示的なベクター長パラメーターを取ります。

<W x T> llvm.vp.<opcode>.*(<W x T> %x, <W x T> %y, <W x i1> %mask, i32 %evl)

ベクターマスクパラメーター(%mask)は、常に<32 x i1>などのi1型のベクターを持ちます。明示的なベクター長パラメーターは、常にi32型を持ち、符号なし整数値です。明示的なベクター長パラメーター(%evl)は、次の範囲内です。

0 <= %evl <= W,  where W is the number of vector elements

スケーラブルベクター型の場合、Wはベクターのランタイム長であることに注意してください。

%evl > Wの場合、VP組み込み関数の動作は未定義です。明示的なベクター長(%evl)は、すべての要素0 <= i < %evlがTrueに設定され、他のすべてのレーン%evl <= i < WがFalseに設定されたマスク、%EVLmaskを作成します。新しいマスク%Mは、%maskと%EVLmaskの要素ごとのANDで計算されます。

M = %mask AND %EVLmask

ベクターABに対するベクター演算<opcode>は、次を計算します。

A <opcode> B =  {  A[i] <opcode> B[i]   M[i] = True, and
                {  undef otherwise

最適化のヒント

AVX512など、一部のターゲットはハードウェアで%evlパラメーターをサポートしていません。これらのターゲットでは、効果的な%evlの使用は推奨されません。ターゲットが%evlのネイティブサポートを持っている場合、関数TargetTransformInfo::hasActiveVectorLength()はtrueを返します。

llvm.vp.select.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.select.v16i32 (<16 x i1> <condition>, <16 x i32> <on_true>, <16 x i32> <on_false>, i32 <evl>)
declare <vscale x 4 x i64>  @llvm.vp.select.nxv4i64 (<vscale x 4 x i1> <condition>, <vscale x 4 x i64> <on_true>, <vscale x 4 x i64> <on_false>, i32 <evl>)
概要:

llvm.vp.select’組み込み関数は、IRレベルの分岐なしで、条件ベクターに基づいて1つの値を選択するために使用されます。

引数:

最初の引数はi1のベクターであり、条件を示します。2番目の引数は、条件ベクターがtrueの場合に選択される値です。3番目の引数は、条件ベクターがfalseの場合に選択される値です。ベクターは同じサイズである必要があります。4番目の引数は、明示的なベクター長です。

  1. オプションの fast-math flags マーカーは、select が1つ以上のfast-math フラグを持っていることを示します。これらは、通常は安全でない浮動小数点最適化を有効にするための最適化ヒントです。fast-math フラグは、浮動小数点スカラー型またはベクトル型、あるいは浮動小数点スカラー型またはベクトル型の配列(任意の深さまでネスト可能)を返す select に対してのみ有効です。

セマンティクス:

組み込み関数は、条件ベクターに応じて、2番目と3番目の引数からレーンを選択します。

%evl以上の位置にあるすべての結果レーンは未定義です。%evl未満のすべてのレーンで、条件ベクターがtrueの場合、レーンは2番目の引数から取得されます。それ以外の場合、レーンは3番目の引数から取得されます。

例:
%r = call <4 x i32> @llvm.vp.select.v4i32(<4 x i1> %cond, <4 x i32> %on_true, <4 x i32> %on_false, i32 %evl)

;;; Expansion.
;; Any result is legal on lanes at and above %evl.
%also.r = select <4 x i1> %cond, <4 x i32> %on_true, <4 x i32> %on_false

llvm.vp.merge.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.merge.v16i32 (<16 x i1> <condition>, <16 x i32> <on_true>, <16 x i32> <on_false>, i32 <pivot>)
declare <vscale x 4 x i64>  @llvm.vp.merge.nxv4i64 (<vscale x 4 x i1> <condition>, <vscale x 4 x i64> <on_true>, <vscale x 4 x i64> <on_false>, i32 <pivot>)
概要:

llvm.vp.merge’組み込み関数は、IRレベルの分岐なしで、条件ベクターとインデックス引数に基づいて1つの値を選択するために使用されます。

引数:

最初の引数はi1のベクターであり、条件を示します。2番目の引数は、条件ベクターがtrueの場合にマージされる値です。3番目の引数は、条件ベクターがfalseの場合、またはレーン位置がピボット以上の場合に選択される値です。4番目の引数は、ピボットです。

  1. オプションのfast-math flagsマーカーは、マージに1つ以上のfast-mathフラグがあることを示します。これらは、安全でない浮動小数点最適化を有効にするための最適化ヒントです。fast-mathフラグは、浮動小数点スカラー型またはベクター型、または浮動小数点スカラー型またはベクター型の配列(任意の深さにネスト)を返すマージに対してのみ有効です。

セマンティクス:

組み込み関数は、条件ベクターとピボット値に応じて、2番目と3番目の引数からレーンを選択します。

条件ベクターがtrueで、レーン位置が%pivot未満であるすべてのレーンでは、レーンは2番目の引数から取得されます。それ以外の場合、レーンは3番目の引数から取得されます。

例:
%r = call <4 x i32> @llvm.vp.merge.v4i32(<4 x i1> %cond, <4 x i32> %on_true, <4 x i32> %on_false, i32 %pivot)

;;; Expansion.
;; Lanes at and above %pivot are taken from %on_false
%atfirst = insertelement <4 x i32> undef, i32 %pivot, i32 0
%splat = shufflevector <4 x i32> %atfirst, <4 x i32> poison, <4 x i32> zeroinitializer
%pivotmask = icmp ult <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> %splat
%mergemask = and <4 x i1> %cond, <4 x i1> %pivotmask
%also.r = select <4 x i1> %mergemask, <4 x i32> %on_true, <4 x i32> %on_false

llvm.vp.add.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.add.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.add.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.add.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き整数加算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.add’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数加算(add)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.add.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = add <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.sub.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.sub.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.sub.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.sub.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き整数減算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.sub’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数減算(sub)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.sub.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = sub <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.mul.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.mul.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.mul.nxv46i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.mul.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き整数乗算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.mul’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数乗算(mul)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.mul.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = mul <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.sdiv.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.sdiv.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.sdiv.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.sdiv.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号付き除算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.sdiv’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の符号付き除算(sdiv)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.sdiv.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = sdiv <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.udiv.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.udiv.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.udiv.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.udiv.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号なし除算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.udiv’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の符号なし除算(udiv)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.udiv.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = udiv <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.srem.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.srem.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.srem.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.srem.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの符号付き剰余の述語付き計算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.srem’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の符号付き除算の剰余(srem)を計算します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.srem.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = srem <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.urem.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.urem.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.urem.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.urem.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの符号なし剰余の述語付き計算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.urem’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の符号なし除算の剰余(urem)を計算します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.urem.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = urem <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.ashr.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.ashr.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.ashr.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.ashr.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付き算術右シフト。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.ashr’ 組み込み関数は、有効なレーンごとに最初の引数を2番目の引数で算術右シフト(ashr)します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.ashr.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = ashr <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.lshr.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.lshr.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.lshr.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.lshr.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付き論理右シフト。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.lshr’ 組み込み関数は、有効なレーンごとに最初の引数を2番目の引数で論理右シフト(lshr)します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.lshr.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = lshr <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.shl.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.shl.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.shl.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.shl.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付き左シフト。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.shl’ 組み込み関数は、有効なレーンごとに最初の引数を2番目の引数で左シフト(shl)します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.shl.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = shl <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.or.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.or.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.or.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.or.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付きor。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.or’ 組み込み関数は、有効なレーンごとに最初の2つの引数のビット単位or(or)を実行します。無効なレーンでの結果は、poison valueです。

例:
%r = call <4 x i32> @llvm.vp.or.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = or <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.and.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.and.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.and.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.and.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付きの and。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.and’ 組み込み関数は、有効なレーンごとに最初の2つの引数のビット単位の and ( and ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.and.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = and <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.xor.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.xor.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.xor.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.xor.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

ベクター述語付き、ビット単位の xor。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.xor’ 組み込み関数は、有効なレーンごとに最初の2つの引数のビット単位の xor ( xor ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.xor.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = xor <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.abs.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.abs.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>, i1 <is_int_min_poison>)
declare <vscale x 4 x i32>  @llvm.vp.abs.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>, i1 <is_int_min_poison>)
declare <256 x i64>  @llvm.vp.abs.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>, i1 <is_int_min_poison>)
概要:

整数のベクターの述語付き abs。

引数:

最初の引数と結果は、同じ整数のベクター型を持ちます。2番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。4番目の引数は定数でなければならず、最初の引数が静的または動的に INT_MIN 値である場合、‘llvm.vp.abs’ 組み込み関数の結果値が poison value であるかどうかを示すフラグです。

セマンティクス:

llvm.vp.abs’ 組み込み関数は、有効なレーンごとに最初の引数の abs ( abs ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.abs.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl, i1 false)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %a, i1 false)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.smax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.smax.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.smax.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.smax.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数のベクターの述語付き整数符号付き最大値。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.smax’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数符号付き最大値 ( smax ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.smax.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.smin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.smin.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.smin.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.smin.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数のベクターの述語付き整数符号付き最小値。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.smin’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数符号付き最小値 ( smin ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.smin.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.umax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.umax.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.umax.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.umax.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数のベクターの述語付き整数符号なし最大値。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.umax’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数符号なし最大値 ( umax ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.umax.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.umin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.umin.v16i32 (<16 x i32> <left_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.umin.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.umin.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数のベクターの述語付き整数符号なし最小値。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.umin’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の整数符号なし最小値 ( umin ) を実行します。無効なレーンの結果は poison value です。

例:
%r = call <4 x i32> @llvm.vp.umin.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.copysign.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.copysign.v16f32 (<16 x float> <mag_op>, <16 x float> <sign_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.copysign.nxv4f32 (<vscale x 4 x float> <mag_op>, <vscale x 4 x float> <sign_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.copysign.v256f64 (<256 x double> <mag_op>, <256 x double> <sign_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの浮動小数点値のベクターの述語付き浮動小数点 copysign。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.copysign’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の浮動小数点 copysign ( copysign ) を実行します。無効なレーンの結果は poison value です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.copysign.v4f32(<4 x float> %mag, <4 x float> %sign, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.copysign.v4f32(<4 x float> %mag, <4 x float> %sign)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.minnum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.minnum.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.minnum.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.minnum.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの浮動小数点値のベクターの述語付き浮動小数点 IEEE-754 minNum。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.minnum’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の浮動小数点最小値 ( minnum ) を実行します。無効なレーンの結果は poison value です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.minnum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.minnum.v4f32(<4 x float> %a, <4 x float> %b)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.maxnum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.maxnum.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.maxnum.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.maxnum.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの浮動小数点値のベクターの述語付き浮動小数点 IEEE-754 maxNum。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.maxnum’ 組み込み関数は、有効なレーンごとに最初のベクター引数と2番目のベクター引数の浮動小数点最大値 ( maxnum ) を実行します。無効なレーンの結果は poison value です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.maxnum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.minimum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.minimum.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.minimum.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.minimum.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

NaN を伝播し、-0.0 を +0.0 より小さいものとして扱う、2つの浮動小数点値のベクターの述語付き浮動小数点最小値。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.minimum’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点最小値(minimum)を計算します。いずれかの引数がNaNの場合、結果はNaNになります。この組み込み関数では、-0.0は+0.0よりも小さいと見なされます。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.minimum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.minimum.v4f32(<4 x float> %a, <4 x float> %b)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.maximum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.maximum.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.maximum.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.maximum.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点最大値で、NaNを伝播し、-0.0を+0.0よりも小さいものとして扱います。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.maximum’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点最大値(maximum)を計算します。いずれかの引数がNaNの場合、結果はNaNになります。この組み込み関数では、-0.0は+0.0よりも小さいと見なされます。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.maximum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.maximum.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fadd.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fadd.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fadd.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fadd.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点加算。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fadd’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点加算(fadd)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fadd.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fadd <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fsub.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fsub.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fsub.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fsub.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点減算。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fsub’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点減算(fsub)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fsub.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fsub <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fmul.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fmul.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fmul.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fmul.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点乗算。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fmul’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点乗算(fmul)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fmul.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fmul <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fdiv.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fdiv.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fdiv.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fdiv.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点除算。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fdiv’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点除算(fdiv)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fdiv.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fdiv <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.frem.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.frem.v16f32 (<16 x float> <left_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.frem.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.frem.v256f64 (<256 x double> <left_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点剰余。

引数:

最初の2つの引数と結果は、同じ浮動小数点型のベクターを持ちます。3番目の引数はベクターマスクで、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.frem’ 組み込み関数は、有効化されたレーンごとに、第1および第2ベクター引数の浮動小数点剰余(frem)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.frem.v4f32(<4 x float> %a, <4 x float> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = frem <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fneg.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fneg.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fneg.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fneg.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点符号反転。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fneg’ 組み込み関数は、有効化されたレーンごとに、最初のベクター引数の浮動小数点符号反転(fneg)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。

例:
%r = call <4 x float> @llvm.vp.fneg.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fneg <4 x float> %a
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fabs.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fabs.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fabs.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fabs.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点絶対値。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fabs’ 組み込み関数は、有効化されたレーンごとに、最初のベクター引数の浮動小数点絶対値(fabs)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。

例:
%r = call <4 x float> @llvm.vp.fabs.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.sqrt.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.sqrt.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.sqrt.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.sqrt.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点平方根。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.sqrt’ 組み込み関数は、有効化されたレーンごとに、最初のベクター引数の浮動小数点平方根(sqrt)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.sqrt.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fma.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fma.v16f32 (<16 x float> <left_op>, <16 x float> <middle_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fma.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <middle_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fma.v256f64 (<256 x double> <left_op>, <256 x double> <middle_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値の2つのベクターの述語付き浮動小数点積和演算。

引数:

最初の3つの引数と結果は、同じ浮動小数点型のベクターを持ちます。4番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。5番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.fma’ 組み込み関数は、有効化されたレーンごとに、最初の、2番目の、および3番目のベクター引数の浮動小数点積和演算(llvm.fma)を実行します。無効化されたレーンでの結果は、poison value(未定義値)です。演算はデフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fma.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.fma(<4 x float> %a, <4 x float> %b, <4 x float> %c)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fmuladd.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fmuladd.v16f32 (<16 x float> <left_op>, <16 x float> <middle_op>, <16 x float> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.fmuladd.nxv4f32 (<vscale x 4 x float> <left_op>, <vscale x 4 x float> <middle_op>, <vscale x 4 x float> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.fmuladd.v256f64 (<256 x double> <left_op>, <256 x double> <middle_op>, <256 x double> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

コードジェネレーターが、(a)ターゲット命令セットが融合演算をサポートしていること、(b)融合演算が同等の別々の乗算命令と加算命令のペアよりも効率的であると判断した場合に、融合可能な浮動小数点値の2つのベクトルの述語付き浮動小数点乗算加算。

引数:

最初の3つの引数と結果は、同じ浮動小数点型のベクターを持ちます。4番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。5番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.fmuladd’ 組み込み関数は、有効な各レーンで、最初のベクトル引数、2番目のベクトル引数、3番目のベクトル引数の浮動小数点乗算加算(llvm.fuladd)を実行します。無効なレーンでの結果は、poison valueです。演算は、デフォルトの浮動小数点環境で実行されます。

例:
%r = call <4 x float> @llvm.vp.fmuladd.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.fmuladd(<4 x float> %a, <4 x float> %b, <4 x float> %c)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.reduce.add.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.add.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.add.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き整数ADD削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.add’ 組み込み関数は、有効な各レーンで、ベクトル引数valの整数ADD削減(llvm.vector.reduce.add)を実行し、それをスカラーstart_valueに追加します。無効なレーンは、ニュートラル値0(つまり、削減演算に影響を与えない)を含むものとして扱われます。ベクトル長がゼロの場合、結果はstart_valueと等しくなります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.add.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> zeroinitializer
%reduction = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %masked.a)
%also.r = add i32 %reduction, %start

llvm.vp.reduce.fadd.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fadd.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare double @llvm.vp.reduce.fadd.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き浮動小数点ADD削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.fadd’ 組み込み関数は、有効な各レーンで、ベクトル引数valの浮動小数点ADD削減(llvm.vector.reduce.fadd)を実行し、それをスカラーstart_valueに追加します。無効なレーンは、ニュートラル値-0.0(つまり、削減演算に影響を与えない)を含むものとして扱われます。有効なレーンがない場合、結果の値はstart_valueと等しくなります。

開始値を無視するには、ニュートラル値を使用できます。

削減の意味の詳細については、非述語バージョン(llvm.vector.reduce.fadd)を参照してください。

例:
%r = call float @llvm.vp.reduce.fadd.v4f32(float %start, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>
%also.r = call float @llvm.vector.reduce.fadd.v4f32(float %start, <4 x float> %masked.a)

llvm.vp.reduce.mul.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.mul.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.mul.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き整数MUL削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.mul’ 組み込み関数は、有効な各レーンで、ベクトル引数valの整数MUL削減(llvm.vector.reduce.mul)を実行し、それをスカラーstart_valueで乗算します。無効なレーンは、ニュートラル値1(つまり、削減演算に影響を与えない)を含むものとして扱われます。ベクトル長がゼロの場合、結果は開始値です。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.mul.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
%reduction = call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %masked.a)
%also.r = mul i32 %reduction, %start

llvm.vp.reduce.fmul.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fmul.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare double @llvm.vp.reduce.fmul.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き浮動小数点MUL削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.fmul’ 組み込み関数は、有効な各レーンで、ベクトル引数valの浮動小数点MUL削減(llvm.vector.reduce.fmul)を実行し、それをスカラーstart_value`で乗算します。無効なレーンは、ニュートラル値1.0(つまり、削減演算に影響を与えない)を含むものとして扱われます。有効なレーンがない場合、結果の値は開始値と等しくなります。

開始値を無視するには、ニュートラル値を使用できます。

意味の詳細については、非述語バージョン(llvm.vector.reduce.fmul)を参照してください。

例:
%r = call float @llvm.vp.reduce.fmul.v4f32(float %start, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>
%also.r = call float @llvm.vector.reduce.fmul.v4f32(float %start, <4 x float> %masked.a)

llvm.vp.reduce.and.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.and.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.and.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き整数AND削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.and’ 組み込み関数は、有効な各レーンで、ベクトル引数valの整数AND削減(llvm.vector.reduce.and)を実行し、それをスカラーstart_valueと ‘and’ します。無効なレーンは、ニュートラル値UINT_MAX、または-1(つまり、削減演算に影響を与えない)を含むものとして扱われます。ベクトル長がゼロの場合、結果は開始値です。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.and.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
%reduction = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %masked.a)
%also.r = and i32 %reduction, %start

llvm.vp.reduce.or.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.or.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.or.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

ベクトルの述語付き整数OR削減とスカラー開始値。結果をスカラーとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

意味:

llvm.vp.reduce.or’ 組み込み関数は、有効な各レーンで、ベクトル引数valの整数OR削減(llvm.vector.reduce.or)を実行し、それをスカラーstart_valueと ‘or’ します。無効なレーンは、ニュートラル値0(つまり、削減演算に影響を与えない)を含むものとして扱われます。ベクトル長がゼロの場合、結果は開始値です。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.or.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
%reduction = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %masked.a)
%also.r = or i32 %reduction, %start

llvm.vp.reduce.xor.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.xor.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.xor.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き整数XORによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.xor’ 組み込み関数は、有効化された各レーンに対してベクター引数valの整数XOR縮約(llvm.vector.reduce.xor)を実行し、スカラstart_valueとの ‘xor’ を実行します。無効化されたレーンは、中立値である0 (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.xor.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
%reduction = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %masked.a)
%also.r = xor i32 %reduction, %start

llvm.vp.reduce.smax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.smax.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.smax.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き符号付き整数MAXによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.smax’ 組み込み関数は、有効化された各レーンに対してベクター引数valの符号付き整数MAX縮約(llvm.vector.reduce.smax)を実行し、スカラstart_valueとの最大値を求めます。無効化されたレーンは、中立値であるINT_MIN (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i8 @llvm.vp.reduce.smax.v4i8(i8 %start, <4 x i8> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i8> %a, <4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>
%reduction = call i8 @llvm.vector.reduce.smax.v4i8(<4 x i8> %masked.a)
%also.r = call i8 @llvm.smax.i8(i8 %reduction, i8 %start)

llvm.vp.reduce.smin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.smin.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.smin.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き符号付き整数MINによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.smin’ 組み込み関数は、有効化された各レーンに対してベクター引数valの符号付き整数MIN縮約(llvm.vector.reduce.smin)を実行し、スカラstart_valueとの最小値を求めます。無効化されたレーンは、中立値であるINT_MAX (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i8 @llvm.vp.reduce.smin.v4i8(i8 %start, <4 x i8> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i8> %a, <4 x i8> <i8 127, i8 127, i8 127, i8 127>
%reduction = call i8 @llvm.vector.reduce.smin.v4i8(<4 x i8> %masked.a)
%also.r = call i8 @llvm.smin.i8(i8 %reduction, i8 %start)

llvm.vp.reduce.umax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.umax.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.umax.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き符号なし整数MAXによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.umax’ 組み込み関数は、有効化された各レーンに対してベクター引数valの符号なし整数MAX縮約(llvm.vector.reduce.umax)を実行し、スカラstart_valueとの最大値を求めます。無効化されたレーンは、中立値である0 (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.umax.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
%reduction = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %masked.a)
%also.r = call i32 @llvm.umax.i32(i32 %reduction, i32 %start)

llvm.vp.reduce.umin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare i32 @llvm.vp.reduce.umin.v4i32(i32 <start_value>, <4 x i32> <val>, <4 x i1> <mask>, i32 <vector_length>)
declare i16 @llvm.vp.reduce.umin.nxv8i16(i16 <start_value>, <vscale x 8 x i16> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き符号なし整数MINによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー整数型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である整数値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.umin’ 組み込み関数は、有効化された各レーンに対してベクター引数valの符号なし整数MIN縮約(llvm.vector.reduce.umin)を実行し、スカラstart_valueとの最小値を求めます。無効化されたレーンは、中立値であるUINT_MAX、または-1 (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call i32 @llvm.vp.reduce.umin.v4i32(i32 %start, <4 x i32> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x i32> %a, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
%reduction = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %masked.a)
%also.r = call i32 @llvm.umin.i32(i32 %reduction, i32 %start)

llvm.vp.reduce.fmax.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fmax.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, float <vector_length>)
declare double @llvm.vp.reduce.fmax.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き浮動小数点MAXによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.fmax’ 組み込み関数は、有効化された各レーンに対してベクター引数valの浮動小数点MAX縮約(llvm.vector.reduce.fmax)を実行し、スカラstart_valueとの最大値を求めます。無効化されたレーンは、中立値 (つまり、縮約演算に影響を与えない) を含むものとして扱われます。ベクター長がゼロの場合、結果は開始値になります。

中立値は、高速数学フラグに依存します。フラグが設定されていない場合、中立値は-QNANです。nnanninf の両方が設定されている場合、中立値は結果の型で最小の浮動小数点値になります。nnan のみが設定されている場合、中立値は-Infinityになります。

この命令は、llvm.vector.reduce.fmax 組み込み関数 (および、したがって ‘llvm.maxnum.*’ 組み込み関数) と同じ比較セマンティクスを持ちます。つまり、ベクターのすべての要素と開始値がNaNでない限り、結果は常に数値になります。最大要素絶対値が0.0で、+0.0-0.0 の両方の要素を含むベクターの場合、結果の符号は未指定です。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call float @llvm.vp.reduce.fmax.v4f32(float %float, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float QNAN, float QNAN, float QNAN, float QNAN>
%reduction = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> %masked.a)
%also.r = call float @llvm.maxnum.f32(float %reduction, float %start)

llvm.vp.reduce.fmin.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fmin.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, float <vector_length>)
declare double @llvm.vp.reduce.fmin.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き浮動小数点MINによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.fmin’ 組み込み関数は、浮動小数点数の MIN 縮約 (llvm.vector.reduce.fmin) を、有効化された各レーンにおいてベクタ引数 val に対して実行し、それとスカラー start_value の最小値を求めます。無効化されたレーンは、中立値を含むものとして扱われます(つまり、縮約演算に影響を与えません)。ベクタ長がゼロの場合、結果は開始値になります。

中立値は、fast-math フラグ に依存します。フラグが設定されていない場合、中立値は +QNAN です。nnanninf の両方が設定されている場合、中立値は結果の型に対する最大の浮動小数点値です。nnan のみが設定されている場合、中立値は +Infinity です。

この命令は、llvm.vector.reduce.fmin 組み込み関数(および ‘llvm.minnum.*’ 組み込み関数)と同じ比較セマンティクスを持ちます。つまり、ベクタのすべての要素と開始値が NaN でない限り、結果は常に数値になります。最大要素の絶対値が 0.0 であり、+0.0-0.0 の両方の要素を含むベクタの場合、結果の符号は指定されていません。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call float @llvm.vp.reduce.fmin.v4f32(float %start, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float QNAN, float QNAN, float QNAN, float QNAN>
%reduction = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> %masked.a)
%also.r = call float @llvm.minnum.f32(float %reduction, float %start)

llvm.vp.reduce.fmaximum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fmaximum.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, float <vector_length>)
declare double @llvm.vp.reduce.fmaximum.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き浮動小数点MAXによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.fmaximum’ 組み込み関数は、浮動小数点数の MAX 縮約 (llvm.vector.reduce.fmaximum) を、有効化された各レーンにおいてベクタ引数 val に対して実行し、それとスカラー start_value の最大値を求めます。無効化されたレーンは、中立値を含むものとして扱われます(つまり、縮約演算に影響を与えません)。ベクタ長がゼロの場合、結果は開始値になります。

中立値は、fast-math フラグ に依存します。フラグが設定されていない場合、または nnan のみが設定されている場合、中立値は -Infinity です。ninf が設定されている場合、中立値は結果の型に対する最小の浮動小数点値です。

この命令は、llvm.vector.reduce.fmaximum 組み込み関数(および ‘llvm.maximum.*’ 組み込み関数)と同じ比較セマンティクスを持ちます。つまり、ベクタの要素または開始値のいずれかが NaN でない限り、結果は常に数値になります。具体的には、この組み込み関数は NaN を伝播します。また、-0.0 は +0.0 より小さいと見なされます。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call float @llvm.vp.reduce.fmaximum.v4f32(float %float, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float -infinity, float -infinity, float -infinity, float -infinity>
%reduction = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> %masked.a)
%also.r = call float @llvm.maximum.f32(float %reduction, float %start)

llvm.vp.reduce.fminimum.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare float @llvm.vp.reduce.fminimum.v4f32(float <start_value>, <4 x float> <val>, <4 x i1> <mask>, float <vector_length>)
declare double @llvm.vp.reduce.fminimum.nxv8f64(double <start_value>, <vscale x 8 x double> <val>, <vscale x 8 x i1> <mask>, i32 <vector_length>)
概要:

述語付き浮動小数点MINによる、ベクターとスカラの開始値の縮約を行い、結果をスカラとして返します。

引数:

最初の引数は削減の開始値であり、結果型と同じスカラー浮動小数点型である必要があります。2番目の引数は、削減が実行されるベクトルであり、要素型が結果/開始型である浮動小数点値のベクトルである必要があります。3番目の引数はベクトルマスクであり、ベクトル引数と同じ数の要素を持つブール値のベクトルです。4番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.reduce.fminimum’ 組み込み関数は、浮動小数点数の MIN 縮約 (llvm.vector.reduce.fminimum) を、有効化された各レーンにおいてベクタ引数 val に対して実行し、それとスカラー start_value の最小値を求めます。無効化されたレーンは、中立値を含むものとして扱われます(つまり、縮約演算に影響を与えません)。ベクタ長がゼロの場合、結果は開始値になります。

中立値は、fast-math フラグ に依存します。フラグが設定されていない場合、または nnan のみが設定されている場合、中立値は +Infinity です。ninf が設定されている場合、中立値は結果の型に対する最大の浮動小数点値です。

この命令は、llvm.vector.reduce.fminimum 組み込み関数(および ‘llvm.minimum.*’ 組み込み関数)と同じ比較セマンティクスを持ちます。つまり、ベクタの要素または開始値のいずれかが NaN でない限り、結果は常に数値になります。具体的には、この組み込み関数は NaN を伝播します。また、-0.0 は +0.0 より小さいと見なされます。

開始値を無視するには、ニュートラル値を使用できます。

例:
%r = call float @llvm.vp.reduce.fminimum.v4f32(float %start, <4 x float> %a, <4 x i1> %mask, i32 %evl)
; %r is equivalent to %also.r, where lanes greater than or equal to %evl
; are treated as though %mask were false for those lanes.

%masked.a = select <4 x i1> %mask, <4 x float> %a, <4 x float> <float infinity, float infinity, float infinity, float infinity>
%reduction = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> %masked.a)
%also.r = call float @llvm.minimum.f32(float %reduction, float %start)

llvm.get.active.lane.mask.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %base, i32 %n)
declare <8 x i1> @llvm.get.active.lane.mask.v8i1.i64(i64 %base, i64 %n)
declare <16 x i1> @llvm.get.active.lane.mask.v16i1.i64(i64 %base, i64 %n)
declare <vscale x 16 x i1> @llvm.get.active.lane.mask.nxv16i1.i64(i64 %base, i64 %n)
概要:

有効および無効なベクタレーンを表すマスクを作成します。

引数:

両方の引数は同じスカラー整数型を持ちます。結果は i1 要素型のベクタです。

セマンティクス:

llvm.get.active.lane.mask.*’ 組み込み関数は、意味的に以下と同等です。

%m[i] = icmp ult (%base + i), %n

ここで、%m は有効/無効なレーンのベクタ(マスク)であり、その要素は i でインデックス付けされています。%base%nllvm.get.active.lane.mask.* への 2 つの引数であり、%icmp は整数比較であり、ult は符号なし小なり比較演算子です。(%base + i) においてオーバーフローは発生せず、%n との比較も、機械数ではなく整数で行われるため、オーバーフローは発生しません。%n0 の場合、結果はポイズン値になります。上記は以下と同等です。

%m = @llvm.get.active.lane.mask(%base, %n)

これは、たとえば、ループベクタライザーによって出力される可能性があり、その場合、%base はベクタ誘導変数(VIV)の最初の要素であり、%n はループトリップカウントです。したがって、これらの組み込み関数は、VIV とループトリップカウントの要素ごとの小なり比較を実行し、VIV がオーバーフローした場合を除いて、有効/無効なベクタレーンを表す true/false 値のマスクを生成します。VIV がオーバーフローしたレーンでは false を返します。引数は、オーバーフローせずにレーンを列挙するステップベクタの型が不明な、スケーラブルベクタ型に対応するためのスカラー型です。

このマスク %m は、たとえば、マスクされたロード/ストア命令で使用できます。これらの組み込み関数は、バックエンドへのヒントを提供します。つまり、ベクトルループの場合、元のスカラーループのバックエッジが取得された回数が 2 番目の引数として明示的です。

例:
%active.lane.mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i64(i64 %elem0, i64 429)
%wide.masked.load = call <4 x i32> @llvm.masked.load.v4i32.p0v4i32(<4 x i32>* %3, i32 4, <4 x i1> %active.lane.mask, <4 x i32> poison)

llvm.experimental.vp.splice’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <2 x double> @llvm.experimental.vp.splice.v2f64(<2 x double> %vec1, <2 x double> %vec2, i32 %imm, <2 x i1> %mask, i32 %evl1, i32 %evl2)
declare <vscale x 4 x i32> @llvm.experimental.vp.splice.nxv4i32(<vscale x 4 x i32> %vec1, <vscale x 4 x i32> %vec2, i32 %imm, <vscale x 4 x i1> %mask, i32 %evl1, i32 %evl2)
概要:

llvm.experimental.vp.splice.*’ 組み込み関数は、‘llvm.vector.splice.*’ 組み込み関数のベクタ長述語付きバージョンです。

引数:

結果と最初の 2 つの引数 vec1 および vec2 は、同じ型のベクタです。3 番目の引数 imm は、オフセットインデックスを示す即値符号付き整数です。4 番目の引数 mask は、ベクタマスクであり、結果と同じ数の要素を持ちます。最後の 2 つの引数 evl1evl2 は、それぞれ vec1vec2 の明示的なベクタ長を示す符号なし整数です。immevl1evl2 は、次の制約を満たす必要があります。-evl1 <= imm < evl10 <= evl1 <= VL、および 0 <= evl2 <= VL。ここで、VL はランタイムベクタ係数です。これらの制約が満たされない場合、組み込み関数は未定義の動作になります。

セマンティクス:

実質的に、この組み込み関数はvec1[0..evl1-1]vec2[0..evl2-1]を連結し、連結されたベクトルのインデックスimm(正の即値の場合)から始まる、サイズevl2のウィンドウ内の要素を選択することで結果ベクトルを作成します。結果ベクトルのevl2を超える要素はundefです。immが負の場合、開始インデックスはevl1 + immです。アクティブなベクトルの長さがevl2の結果ベクトルには、vec1のインデックス[imm..evl1 - 1](負のimmの場合は[evl1 + imm..evl1 -1])からevl1 - imm(負のimmの場合は-imm)個の要素が含まれ、その後にvec2の最初のevl2 - (evl1 - imm)(負のimmの場合はevl2 + imm)個の要素が続きます。evl1 - imm-imm) >= evl2の場合、最初のevl2個の要素のみが考慮され、残りはundefになります。結果ベクトル内でmaskによって無効化されたレーンはpoisonです。

例:
llvm.experimental.vp.splice(<A,B,C,D>, <E,F,G,H>, 1, 2, 3);  ==> <B, E, F, poison> index
llvm.experimental.vp.splice(<A,B,C,D>, <E,F,G,H>, -2, 3, 2); ==> <B, C, poison, poison> trailing elements

llvm.experimental.vp.splat」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <2 x double> @llvm.experimental.vp.splat.v2f64(double %scalar, <2 x i1> %mask, i32 %evl)
declare <vscale x 4 x i32> @llvm.experimental.vp.splat.nxv4i32(i32 %scalar, <vscale x 4 x i1> %mask, i32 %evl)
概要:

llvm.experimental.vp.splat.*」組み込み関数は、特定の有効ベクトル長で述語付きスプラットを作成するためのものです。

引数:

結果はベクトルであり、最初のスカラー引数のスプラットです。2番目の引数maskはベクトルマスクであり、結果と同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

この組み込み関数は、スカラー引数のevl個の要素を持つベクトルをスプラットします。結果ベクトル内でmaskによって無効化されたレーンはpoisonです。evlを超えた要素はpoisonです。

例:
%r = call <4 x float> @llvm.vp.splat.v4f32(float %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r
%e = insertelement <4 x float> poison, float %a, i32 0
%s = shufflevector <4 x float> %e, <4 x float> poison, <4 x i32> zeroinitializer
%also.r = select <4 x i1> %mask, <4 x float> %s, <4 x float> poison

llvm.experimental.vp.reverse」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <2 x double> @llvm.experimental.vp.reverse.v2f64(<2 x double> %vec, <2 x i1> %mask, i32 %evl)
declare <vscale x 4 x i32> @llvm.experimental.vp.reverse.nxv4i32(<vscale x 4 x i32> %vec, <vscale x 4 x i1> %mask, i32 %evl)
概要:

llvm.experimental.vp.reverse.*」組み込み関数は、「llvm.vector.reverse.*」組み込み関数のベクトル長述語付きバージョンです。

引数:

結果と最初の引数vecは同じ型のベクトルです。2番目の引数maskはベクトルマスクであり、結果と同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

この組み込み関数は、ベクトルの最初のevl個の要素の順序を反転します。結果ベクトル内でmaskによって無効化されたレーンはpoisonです。evlを超えた要素はpoisonです。

llvm.vp.load」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x float> @llvm.vp.load.v4f32.p0(ptr %ptr, <4 x i1> %mask, i32 %evl)
declare <vscale x 2 x i16> @llvm.vp.load.nxv2i16.p0(ptr %ptr, <vscale x 2 x i1> %mask, i32 %evl)
declare <8 x float> @llvm.vp.load.v8f32.p1(ptr addrspace(1) %ptr, <8 x i1> %mask, i32 %evl)
declare <vscale x 1 x i64> @llvm.vp.load.nxv1i64.p6(ptr addrspace(6) %ptr, <vscale x 1 x i1> %mask, i32 %evl)
概要:

llvm.vp.load.*」組み込み関数は、llvm.masked.load組み込み関数のベクトル長述語付きバージョンです。

引数:

最初の引数はロードのベースポインタです。2番目の引数は、戻り値の型と同じ数の要素を持つブール値のベクトルです。3番目は、操作の明示的なベクトル長です。戻り値の型とベースポインタの基礎となる型は、同じベクトル型です。

align パラメータ属性は、最初の引数に指定できます。

セマンティクス:

llvm.vp.load」組み込み関数は、「llvm.masked.load」組み込み関数と同じ方法でメモリからベクトルを読み込みます。ここで、マスクは、通常のVPの方法で「mask」引数と「evl」引数の組み合わせから取得されます。一部の「llvm.masked.load」引数には、「llvm.vp.load」に対応する引数はありません。「passthru」引数は暗黙的にpoisonです。「alignment」引数は、提供されている場合はalignパラメータ属性として扱われます。デフォルトのアライメントは、データレイアウト文字列で指定された戻り値の型のABIアライメントとして扱われます。

例:
%r = call <8 x i8> @llvm.vp.load.v8i8.p0(ptr align 2 %ptr, <8 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%also.r = call <8 x i8> @llvm.masked.load.v8i8.p0(ptr %ptr, i32 2, <8 x i1> %mask, <8 x i8> poison)

llvm.vp.store」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare void @llvm.vp.store.v4f32.p0(<4 x float> %val, ptr %ptr, <4 x i1> %mask, i32 %evl)
declare void @llvm.vp.store.nxv2i16.p0(<vscale x 2 x i16> %val, ptr %ptr, <vscale x 2 x i1> %mask, i32 %evl)
declare void @llvm.vp.store.v8f32.p1(<8 x float> %val, ptr addrspace(1) %ptr, <8 x i1> %mask, i32 %evl)
declare void @llvm.vp.store.nxv1i64.p6(<vscale x 1 x i64> %val, ptr addrspace(6) %ptr, <vscale x 1 x i1> %mask, i32 %evl)
概要:

llvm.vp.store.*」組み込み関数は、llvm.masked.store組み込み関数のベクトル長述語付きバージョンです。

引数:

最初の引数は、メモリに書き込まれるベクトル値です。2番目の引数は、ストアのベースポインタです。これは、value引数と同じ基礎となる型を持ちます。3番目の引数は、戻り値の型と同じ数の要素を持つブール値のベクトルです。4番目は、操作の明示的なベクトル長です。

alignパラメータ属性は、2番目の引数に指定できます。

セマンティクス:

llvm.vp.store」組み込み関数は、「llvm.masked.store」組み込み関数と同じ方法でメモリからベクトルを読み込みます。ここで、マスクは、通常のVPの方法で「mask」引数と「evl」引数の組み合わせから取得されます。操作のアライメント(「llvm.masked.store」の「alignment」引数に対応)は、alignパラメータ属性(上記参照)によって指定されます。提供されていない場合、代わりに、データレイアウト文字列で指定された、「value」引数の型のABIアライメントが使用されます。

例:
call void @llvm.vp.store.v8i8.p0(<8 x i8> %val, ptr align 4 %ptr, <8 x i1> %mask, i32 %evl)
;; For all lanes below %evl, the call above is lane-wise equivalent to the call below.

call void @llvm.masked.store.v8i8.p0(<8 x i8> %val, ptr %ptr, i32 4, <8 x i1> %mask)

llvm.experimental.vp.strided.load」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x float> @llvm.experimental.vp.strided.load.v4f32.i64(ptr %ptr, i64 %stride, <4 x i1> %mask, i32 %evl)
declare <vscale x 2 x i16> @llvm.experimental.vp.strided.load.nxv2i16.i64(ptr %ptr, i64 %stride, <vscale x 2 x i1> %mask, i32 %evl)
概要:

llvm.experimental.vp.strided.load」組み込み関数は、「ptr」から始まる、「stride」バイト数で等間隔に離れたメモリ位置からスカラー値をベクトルにロードします。

引数:

最初の引数はロードのベースポインタです。2番目の引数は、バイト単位で表されるストライド値です。3番目の引数は、戻り値の型と同じ数の要素を持つブール値のベクトルです。4番目は、操作の明示的なベクトル長です。ベースポインタの基礎となる型は、戻り値の引数のスカラー要素の型と一致します。

align パラメータ属性は、最初の引数に指定できます。

セマンティクス:

llvm.experimental.vp.strided.load」組み込み関数は、llvm.vp.gather組み込み関数と同じ方法で、メモリから複数のスカラー値をベクトルにロードします。ここで、ポインタのベクトルは次の形式になります。

%ptrs = <%ptr, %ptr + %stride, %ptr + 2 * %stride, ... >,

ここで、「ptr」は以前にポインタ「i8」にキャストされ、「stride」は常に符号付き整数として解釈され、すべての算術はポインタ型で発生します。

例:
%r = call <8 x i64> @llvm.experimental.vp.strided.load.v8i64.i64(i64* %ptr, i64 %stride, <8 x i64> %mask, i32 %evl)
;; The operation can also be expressed like this:

%addr = bitcast i64* %ptr to i8*
;; Create a vector of pointers %addrs in the form:
;; %addrs = <%addr, %addr + %stride, %addr + 2 * %stride, ...>
%ptrs = bitcast <8 x i8* > %addrs to <8 x i64* >
%also.r = call <8 x i64> @llvm.vp.gather.v8i64.v8p0i64(<8 x i64* > %ptrs, <8 x i64> %mask, i32 %evl)

llvm.experimental.vp.strided.store」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare void @llvm.experimental.vp.strided.store.v4f32.i64(<4 x float> %val, ptr %ptr, i64 %stride, <4 x i1> %mask, i32 %evl)
declare void @llvm.experimental.vp.strided.store.nxv2i16.i64(<vscale x 2 x i16> %val, ptr %ptr, i64 %stride, <vscale x 2 x i1> %mask, i32 %evl)
概要:

@llvm.experimental.vp.strided.store’ 組み込み関数は、 ‘val’ の要素を、’ptr’ から開始して ‘stride’ バイト間隔で均等に離れたメモリ位置に格納します。

引数:

最初の引数はメモリに書き込まれるベクトル値です。2番目の引数はストアのベースポインタです。その基礎となる型は、値の引数のスカラー要素型と一致します。3番目の引数は、バイト単位で表されるストライド値です。4番目の引数は、戻り値の型と同じ要素数を持つブール値のベクトルです。5番目は操作の明示的なベクトル長です。

alignパラメータ属性は、2番目の引数に指定できます。

セマンティクス:

llvm.experimental.vp.strided.store’ 組み込み関数は、 llvm.vp.scatter 組み込み関数と同じ方法で ‘val’ の要素を格納します。ここで、ポインタのベクトルは次の形式になります。

%ptrs = <%ptr, %ptr + %stride, %ptr + 2 * %stride, ... >,

ここで、「ptr」は以前にポインタ「i8」にキャストされ、「stride」は常に符号付き整数として解釈され、すべての算術はポインタ型で発生します。

例:
call void @llvm.experimental.vp.strided.store.v8i64.i64(<8 x i64> %val, i64* %ptr, i64 %stride, <8 x i1> %mask, i32 %evl)
;; The operation can also be expressed like this:

%addr = bitcast i64* %ptr to i8*
;; Create a vector of pointers %addrs in the form:
;; %addrs = <%addr, %addr + %stride, %addr + 2 * %stride, ...>
%ptrs = bitcast <8 x i8* > %addrs to <8 x i64* >
call void @llvm.vp.scatter.v8i64.v8p0i64(<8 x i64> %val, <8 x i64*> %ptrs, <8 x i1> %mask, i32 %evl)

llvm.vp.gather’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <4 x double> @llvm.vp.gather.v4f64.v4p0(<4 x ptr> %ptrs, <4 x i1> %mask, i32 %evl)
declare <vscale x 2 x i8> @llvm.vp.gather.nxv2i8.nxv2p0(<vscale x 2 x ptr> %ptrs, <vscale x 2 x i1> %mask, i32 %evl)
declare <2 x float> @llvm.vp.gather.v2f32.v2p2(<2 x ptr addrspace(2)> %ptrs, <2 x i1> %mask, i32 %evl)
declare <vscale x 4 x i32> @llvm.vp.gather.nxv4i32.nxv4p4(<vscale x 4 x ptr addrspace(4)> %ptrs, <vscale x 4 x i1> %mask, i32 %evl)
概要:

llvm.vp.gather.*’ 組み込み関数は、 llvm.masked.gather 組み込み関数のベクトル長述語付きバージョンです。

引数:

最初の引数は、読み取るすべてのメモリアドレスを保持するポインタのベクトルです。2番目の引数は、戻り値の型と同じ要素数を持つブール値のベクトルです。3番目は、操作の明示的なベクトル長です。戻り値の型とポインタベクトルの基礎となる型は、同じベクトル型です。

align パラメータ属性は、最初の引数に指定できます。

セマンティクス:

llvm.vp.gather’ 組み込み関数は、 ‘llvm.masked.gather’ 組み込み関数と同じ方法で、メモリから複数のスカラー値を読み取ります。ここで、マスクは、通常の VP 方式で ‘mask’ と ‘evl’ 引数の組み合わせから取得されます。特定の ‘llvm.masked.gather’ 引数は、 ‘llvm.vp.gather’ に対応する引数を持っていません。 ‘passthru’ 引数は暗黙的に poison です。 ‘alignment’ 引数は、提供されている場合は align パラメータとして取得されます。デフォルトのアラインメントは、 datalayout 文字列 で指定されたソースアドレスの ABI アラインメントとして取得されます。

例:
%r = call <8 x i8> @llvm.vp.gather.v8i8.v8p0(<8 x ptr>  align 8 %ptrs, <8 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%also.r = call <8 x i8> @llvm.masked.gather.v8i8.v8p0(<8 x ptr> %ptrs, i32 8, <8 x i1> %mask, <8 x i8> poison)

llvm.vp.scatter’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare void @llvm.vp.scatter.v4f64.v4p0(<4 x double> %val, <4 x ptr> %ptrs, <4 x i1> %mask, i32 %evl)
declare void @llvm.vp.scatter.nxv2i8.nxv2p0(<vscale x 2 x i8> %val, <vscale x 2 x ptr> %ptrs, <vscale x 2 x i1> %mask, i32 %evl)
declare void @llvm.vp.scatter.v2f32.v2p2(<2 x float> %val, <2 x ptr addrspace(2)> %ptrs, <2 x i1> %mask, i32 %evl)
declare void @llvm.vp.scatter.nxv4i32.nxv4p4(<vscale x 4 x i32> %val, <vscale x 4 x ptr addrspace(4)> %ptrs, <vscale x 4 x i1> %mask, i32 %evl)
概要:

llvm.vp.scatter.*’ 組み込み関数は、 llvm.masked.scatter 組み込み関数のベクトル長述語付きバージョンです。

引数:

最初の引数は、メモリに書き込まれるベクトル値です。2番目の引数は、値の要素を格納する場所を指すポインタのベクトルです。3番目の引数は、戻り値の型と同じ要素数を持つブール値のベクトルです。4番目は、操作の明示的なベクトル長です。

alignパラメータ属性は、2番目の引数に指定できます。

セマンティクス:

llvm.vp.scatter’ 組み込み関数は、 ‘llvm.masked.scatter’ 組み込み関数と同じ方法で、複数のスカラー値をメモリに書き込みます。ここで、マスクは、通常の VP 方式で ‘mask’ と ‘evl’ 引数の組み合わせから取得されます。 ‘llvm.masked.scatter’ の ‘alignment’ 引数には、 ‘llvm.vp.scatter’ に対応する引数がありません。代わりに、ポインタのベクトル引数にオプションの align パラメータ属性を介して提供されます。それ以外の場合は、 datalayout 文字列 で指定された宛先アドレスの ABI アラインメントとして取得されます。

例:
call void @llvm.vp.scatter.v8i8.v8p0(<8 x i8> %val, <8 x ptr> align 1 %ptrs, <8 x i1> %mask, i32 %evl)
;; For all lanes below %evl, the call above is lane-wise equivalent to the call below.

call void @llvm.masked.scatter.v8i8.v8p0(<8 x i8> %val, <8 x ptr> %ptrs, i32 1, <8 x i1> %mask)

llvm.vp.trunc.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i16>  @llvm.vp.trunc.v16i16.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i16>  @llvm.vp.trunc.nxv4i16.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.trunc’ 組み込み関数は、最初の引数を戻り値の型に切り捨てます。この操作には、マスクと明示的なベクトル長パラメータがあります。

引数:

llvm.vp.trunc’ 組み込み関数は、キャストする値を最初の引数として取ります。戻り値の型は、値をキャストする型です。両方の型は、整数 型のベクトルである必要があります。値のビットサイズは、戻り値のビットサイズよりも大きい必要があります。2番目の引数は、ベクトルマスクです。戻り値の型、キャストする値、およびベクトルマスクは、同じ要素数を持ちます。3番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.trunc’ 組み込み関数は、値の上位ビットを切り捨て、残りのビットを戻り値の型に変換します。ソースサイズは宛先サイズよりも大きい必要があるため、 ‘llvm.vp.trunc’ はno-op キャストにすることはできません。常にビットを切り捨てます。変換は、明示的なベクトル長よりも小さいレーン位置と、ベクトルマスクが true の場所で実行されます。マスクされたレーンは poison です。

例:
%r = call <4 x i16> @llvm.vp.trunc.v4i16.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = trunc <4 x i32> %a to <4 x i16>
%also.r = select <4 x i1> %mask, <4 x i16> %t, <4 x i16> poison

llvm.vp.zext.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.zext.v16i32.v16i16 (<16 x i16> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.zext.nxv4i32.nxv4i16 (<vscale x 4 x i16> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.zext’ 組み込み関数は、最初の引数を戻り値の型にゼロ拡張します。この操作には、マスクと明示的なベクトル長パラメータがあります。

引数:

llvm.vp.zext’ 組み込み関数は、キャストする値を最初の引数として取ります。戻り値の型は、値をキャストする型です。両方の型は、整数 型のベクトルである必要があります。値のビットサイズは、戻り値のビットサイズよりも小さい必要があります。2番目の引数は、ベクトルマスクです。戻り値の型、キャストする値、およびベクトルマスクは、同じ要素数を持ちます。3番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.zext’ 組み込み関数は、値の上位ビットをゼロビットで埋めて、戻り値の型に達するまで拡張します。i1 からゼロ拡張する場合、結果は常に 0 または 1 になります。変換は、明示的なベクトル長よりも小さいレーン位置と、ベクトルマスクが true の場所で実行されます。マスクされたレーンは poison です。

例:
%r = call <4 x i32> @llvm.vp.zext.v4i32.v4i16(<4 x i16> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = zext <4 x i16> %a to <4 x i32>
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.sext.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.sext.v16i32.v16i16 (<16 x i16> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.sext.nxv4i32.nxv4i16 (<vscale x 4 x i16> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.sext’ 組み込み関数は、最初の引数を戻り値の型に符号拡張します。この操作には、マスクと明示的なベクトル長パラメータがあります。

引数:

llvm.vp.sext’ 組み込み関数は、キャストする値を最初の引数として取ります。戻り値の型は、値をキャストする型です。両方の型は、整数 型のベクトルである必要があります。値のビットサイズは、戻り値のビットサイズよりも小さい必要があります。2番目の引数は、ベクトルマスクです。戻り値の型、キャストする値、およびベクトルマスクは、同じ要素数を持ちます。3番目の引数は、操作の明示的なベクトル長です。

セマンティクス:

llvm.vp.sext’ 組み込み関数は、値の符号ビット(最上位ビット)をコピーして、戻り値のサイズに達するまで符号拡張を実行します。i1 から符号拡張する場合、結果は常に -1 または 0 になります。変換は、明示的なベクトル長よりも小さいレーン位置と、ベクトルマスクが true の場所で実行されます。マスクされたレーンは poison です。

例:
%r = call <4 x i32> @llvm.vp.sext.v4i32.v4i16(<4 x i16> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = sext <4 x i16> %a to <4 x i32>
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.fptrunc.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.fptrunc.v16f32.v16f64 (<16 x double> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.trunc.nxv4f32.nxv4f64 (<vscale x 4 x double> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.fptrunc’ 組み込み関数は、最初の引数を戻り値の型に切り捨てます。この操作には、マスクと明示的なベクトル長パラメータがあります。

引数:

llvm.vp.fptrunc’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。戻り値の型は、値をキャストする型です。両方の型は、浮動小数点型のベクトルでなければなりません。値のビットサイズは、戻り値の型のビットサイズよりも大きくなければなりません。これは、 ‘llvm.vp.fptrunc’ がno-opキャストを行うために使用できないことを意味します。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.fptrunc’ 組み込み関数は、より大きな浮動小数点型からより小さな浮動小数点型にvalueをキャストします。この命令は、デフォルトの浮動小数点環境で実行されると想定されています。変換は、明示的なベクター長よりも小さく、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンはpoisonです。

例:
%r = call <4 x float> @llvm.vp.fptrunc.v4f32.v4f64(<4 x double> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fptrunc <4 x double> %a to <4 x float>
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.fpext.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x double>  @llvm.vp.fpext.v16f64.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x double>  @llvm.vp.fpext.nxv4f64.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.fpext’ 組み込み関数は、最初の引数を戻り値の型に拡張します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.fpext’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。戻り値の型は、値をキャストする型です。両方の型は、浮動小数点型のベクトルでなければなりません。値のビットサイズは、戻り値の型のビットサイズよりも小さくなければなりません。これは、‘llvm.vp.fpext’ がno-opキャストを行うために使用できないことを意味します。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.fpext’ 組み込み関数は、より小さい浮動小数点型からより大きい浮動小数点型にvalueを拡張します。‘llvm.vp.fpext’ は、常にビットを変更するため、no-opキャストを行うために使用することはできません。浮動小数点キャストでno-opキャストを行うには、bitcastを使用してください。変換は、明示的なベクター長よりも小さく、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンはpoisonです。

例:
%r = call <4 x double> @llvm.vp.fpext.v4f64.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fpext <4 x float> %a to <4 x double>
%also.r = select <4 x i1> %mask, <4 x double> %t, <4 x double> poison

llvm.vp.fptoui.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.fptoui.v16i32.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.fptoui.nxv4i32.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.fptoui.v256i64.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.fptoui’ 組み込み関数は、浮動小数点引数を符号なし整数型の戻り値に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.fptoui’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。キャストする値は、浮動小数点型のベクターでなければなりません。戻り値の型は、値をキャストする型です。戻り値の型は、整数型のベクターでなければなりません。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.fptoui’ 組み込み関数は、明示的なベクター長よりも小さく、ベクターマスクが真であるレーン位置で、浮動小数点引数を、最も近い(ゼロ方向に丸められた)符号なし整数値に変換します。マスクオフされたレーンはpoisonです。変換が行われる有効なレーンで、値が戻り値の型に収まらない場合、そのレーンの結果はpoison値になります。

例:
%r = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fptoui <4 x float> %a to <4 x i32>
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.fptosi.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.fptosi.v16i32.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.fptosi.nxv4i32.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.fptosi.v256i64.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.fptosi’ 組み込み関数は、浮動小数点引数を符号付き整数型の戻り値に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.fptosi’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。キャストする値は、浮動小数点型のベクターでなければなりません。戻り値の型は、値をキャストする型です。戻り値の型は、整数型のベクターでなければなりません。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.fptosi’ 組み込み関数は、明示的なベクター長よりも小さく、ベクターマスクが真であるレーン位置で、浮動小数点引数を、最も近い(ゼロ方向に丸められた)符号付き整数値に変換します。マスクオフされたレーンはpoisonです。変換が行われる有効なレーンで、値が戻り値の型に収まらない場合、そのレーンの結果はpoison値になります。

例:
%r = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fptosi <4 x float> %a to <4 x i32>
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.uitofp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.uitofp.v16f32.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.uitofp.nxv4f32.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.uitofp.v256f64.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.uitofp’ 組み込み関数は、符号なし整数引数を浮動小数点型の戻り値に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.uitofp’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。キャストする値は、整数型のベクターでなければなりません。戻り値の型は、値をキャストする型です。戻り値の型は、浮動小数点型のベクターでなければなりません。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.uitofp’ 組み込み関数は、最初の引数を符号なし整数量として解釈し、対応する浮動小数点値に変換します。値を正確に表現できない場合は、デフォルトの丸めモードを使用して丸められます。変換は、明示的なベクター長よりも小さく、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンはpoisonです。

例:
%r = call <4 x float> @llvm.vp.uitofp.v4f32.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = uitofp <4 x i32> %a to <4 x float>
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.sitofp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.sitofp.v16f32.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.sitofp.nxv4f32.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.sitofp.v256f64.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.sitofp’ 組み込み関数は、符号付き整数引数を浮動小数点型の戻り値に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.sitofp’ 組み込み関数は、最初の引数としてキャストする値を受け取ります。キャストする値は、整数型のベクターでなければなりません。戻り値の型は、値をキャストする型です。戻り値の型は、浮動小数点型のベクターでなければなりません。2番目の引数はベクターマスクです。戻り値の型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.sitofp’ 組み込み関数は、その最初の引数を符号付き整数として解釈し、対応する浮動小数点値に変換します。値を正確に表現できない場合は、デフォルトの丸めモードを使用して丸められます。変換は、明示的なベクター長を下回り、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンは poison です。

例:
%r = call <4 x float> @llvm.vp.sitofp.v4f32.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = sitofp <4 x i32> %a to <4 x float>
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.ptrtoint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i8>  @llvm.vp.ptrtoint.v16i8.v16p0(<16 x ptr> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i8>  @llvm.vp.ptrtoint.nxv4i8.nxv4p0(<vscale x 4 x ptr> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.ptrtoint.v16i64.v16p0(<256 x ptr> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.ptrtoint’ 組み込み関数は、そのポインターを整数戻り値型に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.ptrtoint’ 組み込み関数は、キャストする値を最初の引数として受け取ります。これはポインターのベクターである必要があり、キャスト先の型を戻り値型として受け取ります。これは integer 型のベクターである必要があります。2番目の引数はベクターマスクです。戻り値型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.ptrtoint’ 組み込み関数は、ポインター値を整数として解釈し、その値を整数型のサイズに切り捨てるかゼロ拡張することにより、値を戻り値型に変換します。 value が戻り値型よりも小さい場合、ゼロ拡張が行われます。 value が戻り値型よりも大きい場合、切り捨てが行われます。それらが同じサイズの場合、型の変更以外の何も行われません(*no-op cast*)。変換は、明示的なベクター長を下回り、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンは poison です。

例:
%r = call <4 x i8> @llvm.vp.ptrtoint.v4i8.v4p0i32(<4 x ptr> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = ptrtoint <4 x ptr> %a to <4 x i8>
%also.r = select <4 x i1> %mask, <4 x i8> %t, <4 x i8> poison

llvm.vp.inttoptr.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x ptr>  @llvm.vp.inttoptr.v16p0.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x ptr>  @llvm.vp.inttoptr.nxv4p0.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x ptr>  @llvm.vp.inttoptr.v256p0.v256i32 (<256 x i32> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.inttoptr’ 組み込み関数は、その整数値をポインター戻り値型に変換します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.inttoptr’ 組み込み関数は、キャストする値を最初の引数として受け取ります。これは integer 型のベクターである必要があり、キャスト先の型を戻り値型として受け取ります。これはポインター型のベクターである必要があります。2番目の引数はベクターマスクです。戻り値型、キャストする値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.inttoptr’ 組み込み関数は、整数 value のサイズに応じて、ゼロ拡張または切り捨てのいずれかを適用することにより、value を戻り値型に変換します。 value がポインターのサイズよりも大きい場合、切り捨てが行われます。 value がポインターのサイズよりも小さい場合、ゼロ拡張が行われます。それらが同じサイズの場合、何も行われません(*no-op cast*)。変換は、明示的なベクター長を下回り、ベクターマスクが真であるレーン位置で実行されます。マスクオフされたレーンは poison です。

例:
%r = call <4 x ptr> @llvm.vp.inttoptr.v4p0i32.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = inttoptr <4 x i32> %a to <4 x ptr>
%also.r = select <4 x i1> %mask, <4 x ptr> %t, <4 x ptr> poison

llvm.vp.fcmp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i1> @llvm.vp.fcmp.v16f32(<16 x float> <left_op>, <16 x float> <right_op>, metadata <condition code>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i1> @llvm.vp.fcmp.nxv4f32(<vscale x 4 x float> <left_op>, <vscale x 4 x float> <right_op>, metadata <condition code>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i1> @llvm.vp.fcmp.v256f64(<256 x double> <left_op>, <256 x double> <right_op>, metadata <condition code>, <256 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.fcmp’ 組み込み関数は、その引数の比較に基づいてブール値のベクターを返します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.fcmp’ 組み込み関数は、比較する2つの値を最初と2番目の引数として受け取ります。これらの2つの値は、floating-point 型のベクターである必要があります。戻り値型は比較の結果です。戻り値型は、i1 型のベクターである必要があります。4番目の引数はベクターマスクです。戻り値型、比較する値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、実行する比較の種類を示す条件コードです。これは、サポートされている浮動小数点条件コード値の1つを含むメタデータ文字列である必要があります。5番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.fcmp’ は、3番目の引数として与えられた条件コードに従って、最初の2つの引数を比較します。引数は、比較のセマンティクスが条件コードに従って定義されている、有効になっている各レーンで要素ごとに比較されます。マスクオフされたレーンは poison です。

例:
%r = call <4 x i1> @llvm.vp.fcmp.v4f32(<4 x float> %a, <4 x float> %b, metadata !"oeq", <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = fcmp oeq <4 x float> %a, %b
%also.r = select <4 x i1> %mask, <4 x i1> %t, <4 x i1> poison

llvm.vp.icmp.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <32 x i1> @llvm.vp.icmp.v32i32(<32 x i32> <left_op>, <32 x i32> <right_op>, metadata <condition code>, <32 x i1> <mask>, i32 <vector_length>)
declare <vscale x 2 x i1> @llvm.vp.icmp.nxv2i32(<vscale x 2 x i32> <left_op>, <vscale x 2 x i32> <right_op>, metadata <condition code>, <vscale x 2 x i1> <mask>, i32 <vector_length>)
declare <128 x i1> @llvm.vp.icmp.v128i8(<128 x i8> <left_op>, <128 x i8> <right_op>, metadata <condition code>, <128 x i1> <mask>, i32 <vector_length>)
概要:

llvm.vp.icmp’ 組み込み関数は、その引数の比較に基づいてブール値のベクターを返します。この操作には、マスクと明示的なベクター長のパラメーターがあります。

引数:

llvm.vp.icmp’ 組み込み関数は、比較する2つの値を最初と2番目の引数として受け取ります。これらの2つの値は、integer 型のベクターである必要があります。戻り値型は比較の結果です。戻り値型は、i1 型のベクターである必要があります。4番目の引数はベクターマスクです。戻り値型、比較する値、およびベクターマスクは、同じ数の要素を持ちます。3番目の引数は、実行する比較の種類を示す条件コードです。これは、サポートされている整数条件コード値の1つを含むメタデータ文字列である必要があります。5番目の引数は、操作の明示的なベクター長です。

セマンティクス:

llvm.vp.icmp’ は、3番目の引数として与えられた条件コードに従って、最初の2つの引数を比較します。引数は、比較のセマンティクスが条件コードに従って定義されている、有効になっている各レーンで要素ごとに比較されます。マスクオフされたレーンは poison です。

例:
%r = call <4 x i1> @llvm.vp.icmp.v4i32(<4 x i32> %a, <4 x i32> %b, metadata !"ne", <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = icmp ne <4 x i32> %a, %b
%also.r = select <4 x i1> %mask, <4 x i1> %t, <4 x i1> poison

llvm.vp.ceil.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.ceil.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.ceil.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.ceil.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点天井関数。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.ceil’ 組み込み関数は、有効になっている各レーンで、最初のベクター引数の浮動小数点天井関数(ceil)を実行します。無効になっているレーンでの結果は、poison valueです。

例:
%r = call <4 x float> @llvm.vp.ceil.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.floor.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.floor.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.floor.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.floor.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点床関数。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.floor’ 組み込み関数は、有効になっている各レーンで、最初のベクター引数の浮動小数点床関数(floor)を実行します。無効になっているレーンでの結果は、poison valueです。

例:
%r = call <4 x float> @llvm.vp.floor.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.floor.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.rint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.rint.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.rint.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.rint.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクターの述語付き浮動小数点 rint 関数。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

セマンティクス:

llvm.vp.rint’ 組み込み関数は、有効になっている各レーンで、最初のベクター引数の浮動小数点 rint 関数(rint)を実行します。無効になっているレーンでの結果は、poison valueです。

例:
%r = call <4 x float> @llvm.vp.rint.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.rint.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.nearbyint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.nearbyint.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.nearbyint.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.nearbyint.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き nearbyint 演算。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.nearbyint’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の浮動小数点 nearbyint (nearbyint) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x float> @llvm.vp.nearbyint.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.round.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.round.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.round.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.round.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き round 演算。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.round’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の浮動小数点 round (round) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x float> @llvm.vp.round.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.round.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.roundeven.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.roundeven.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.roundeven.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.roundeven.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き roundeven 演算。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.roundeven’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の浮動小数点 roundeven (roundeven) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x float> @llvm.vp.roundeven.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.roundeven.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.roundtozero.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x float>  @llvm.vp.roundtozero.v16f32 (<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x float>  @llvm.vp.roundtozero.nxv4f32 (<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x double>  @llvm.vp.roundtozero.v256f64 (<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き round-to-zero 演算。

引数:

最初の引数と結果は、同じ浮動小数点型のベクターを持ちます。2番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。3番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.roundtozero’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の浮動小数点 roundeven (llvm.trunc) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x float> @llvm.vp.roundtozero.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> poison

llvm.vp.lrint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32> @llvm.vp.lrint.v16i32.v16f32(<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32> @llvm.vp.lrint.nxv4i32.nxv4f32(<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64> @llvm.vp.lrint.v256i64.v256f64(<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き lrint 演算。

引数:

結果は整数ベクトルであり、最初の引数は結果ベクトル型と同じ数の要素を持つ浮動小数点型のベクトルです。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.lrint’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の lrint (lrint) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.lrint.v4i32.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.lrint.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.llrint.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32> @llvm.vp.llrint.v16i32.v16f32(<16 x float> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32> @llvm.vp.llrint.nxv4i32.nxv4f32(<vscale x 4 x float> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64> @llvm.vp.llrint.v256i64.v256f64(<256 x double> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

浮動小数点値のベクトルの条件付き llrint 演算。

引数:

結果は整数ベクトルであり、最初の引数は結果ベクトル型と同じ数の要素を持つ浮動小数点型のベクトルです。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.llrint’ 組み込み関数は、有効になっているレーンごとに、最初のベクトル引数の lrint (llrint) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.llrint.v4i32.v4f32(<4 x float> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.llrint.v4f32(<4 x float> %a)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.bitreverse.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.bitreverse.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.bitreverse.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.bitreverse.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

整数ベクトルの条件付き bitreverse 演算。

引数:

最初の引数と結果は、同じ整数型のベクトルを持ちます。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.bitreverse’ 組み込み関数は、有効になっているレーンごとに、最初の引数の bitreverse (bitreverse) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.bitreverse.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> %a)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.bswap.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.bswap.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.bswap.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.bswap.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

整数ベクトルの条件付き bswap 演算。

引数:

最初の引数と結果は、同じ整数型のベクトルを持ちます。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.bswap’ 組み込み関数は、有効になっているレーンごとに、最初の引数の bswap (bswap) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.bswap.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %a)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.ctpop.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.ctpop.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.ctpop.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.ctpop.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

整数ベクトルの条件付き ctpop 演算。

引数:

最初の引数と結果は、同じ整数型のベクトルを持ちます。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.ctpop’ 組み込み関数は、有効になっているレーンごとに、最初の引数の ctpop (ctpop) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.ctpop.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.ctlz.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.ctlz.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
declare <vscale x 4 x i32>  @llvm.vp.ctlz.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
declare <256 x i64>  @llvm.vp.ctlz.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
概要:

整数ベクトルの条件付き ctlz 演算。

引数:

最初の引数と結果は、同じ整数型のベクトルを持ちます。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。4 番目の引数は、最初の引数がゼロの場合に組み込み関数が有効な結果を返すかどうかを示す定数フラグです。最初の引数がゼロで、4 番目の引数が true の場合、結果は poison です。

意味:

llvm.vp.ctlz’ 組み込み関数は、有効になっているレーンごとに、最初の引数の ctlz (ctlz) を実行します。無効になっているレーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.ctlz.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl, i1 false)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.cttz.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.cttz.v16i32 (<16 x i32> <op>, <16 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
declare <vscale x 4 x i32>  @llvm.vp.cttz.nxv4i32 (<vscale x 4 x i32> <op>, <vscale x 4 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
declare <256 x i64>  @llvm.vp.cttz.v256i64 (<256 x i64> <op>, <256 x i1> <mask>, i32 <vector_length>, i1 <is_zero_poison>)
概要:

整数ベクトルの条件付き cttz 演算。

引数:

最初の引数と結果は、同じ整数型のベクトルを持ちます。2 番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。3 番目の引数は、演算の明示的なベクトル長です。4 番目の引数は、最初の引数がゼロの場合に組み込み関数が有効な結果を返すかどうかを示す定数フラグです。最初の引数がゼロで、4 番目の引数が true の場合、結果は poison です。

意味:

llvm.vp.cttz’ 組み込み関数は、各有効レーンで、第一引数の cttz (cttz) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.cttz.v4i32(<4 x i32> %a, <4 x i1> %mask, i32 %evl, i1 false)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 false)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.cttz.elts.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。固定幅とスケーラブルの両方の整数要素の任意のベクトルに対して `llvm.vp.cttz.elts` を使用できます。

declare i32  @llvm.vp.cttz.elts.i32.v16i32 (<16 x i32> <op>, i1 <is_zero_poison>, <16 x i1> <mask>, i32 <vector_length>)
declare i64  @llvm.vp.cttz.elts.i64.nxv4i32 (<vscale x 4 x i32> <op>, i1 <is_zero_poison>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare i64  @llvm.vp.cttz.elts.i64.v256i1 (<256 x i1> <op>, i1 <is_zero_poison>, <256 x i1> <mask>, i32 <vector_length>)
概要:

この ‘`llvm.vp.cttz.elts`’ 組み込み関数は、ベクトルの末尾のゼロ要素の数をカウントします。これは基本的に、‘`llvm.experimental.cttz.elts`’ のベクトル述語バージョンです。

引数:

最初の引数は、カウントされるベクターです。この引数は、整数要素型を持つベクターでなければなりません。戻り値の型も、ソースベクターの最大要素数を保持するのに十分な幅を持つ整数型でなければなりません。戻り値の型が入力ベクターの要素数に対して十分な幅を持たない場合、この組み込み関数の動作は未定義です。

第二引数は、第一引数がすべてゼロの場合に、組み込み関数が有効な結果を返すかどうかを示す定数フラグです。

第三引数はベクトルマスクであり、入力ベクトル型と同じ数の要素を持ちます。第四引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.cttz.elts’ 組み込み関数は、各有効レーンで、第一引数の末尾 (最下位 / 最も番号の小さい) のゼロ要素をカウントします。第一引数がすべてゼロで、第二引数が true の場合、結果は poison です。それ以外の場合は、明示的なベクトル長 (つまり、第四引数) を返します。

llvm.vp.sadd.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.sadd.sat.v16i32 (<16 x i32> <left_op> <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.sadd.sat.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.sadd.sat.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号付き飽和加算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.sadd.sat’ 組み込み関数は、各有効レーンで、第一および第二ベクトル引数の sadd.sat (sadd.sat) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.sadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.uadd.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.uadd.sat.v16i32 (<16 x i32> <left_op> <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.uadd.sat.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.uadd.sat.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号なし飽和加算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.uadd.sat’ 組み込み関数は、各有効レーンで、第一および第二ベクトル引数の uadd.sat (uadd.sat) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.uadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.ssub.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.ssub.sat.v16i32 (<16 x i32> <left_op> <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.ssub.sat.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.ssub.sat.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号付き飽和減算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.ssub.sat’ 組み込み関数は、各有効レーンで、第一および第二ベクトル引数の ssub.sat (ssub.sat) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.ssub.sat.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.usub.sat.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.usub.sat.v16i32 (<16 x i32> <left_op> <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.usub.sat.nxv4i32 (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.usub.sat.v256i64 (<256 x i64> <left_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

2つの整数ベクトルの述語付き符号なし飽和減算。

引数:

最初の2つの引数と結果は、同じ整数型ベクトルを持ちます。3番目の引数はベクターマスクであり、結果ベクター型と同じ数の要素を持ちます。4番目の引数は、演算の明示的なベクター長です。

意味:

llvm.vp.usub.sat’ 組み込み関数は、各有効レーンで、第一および第二ベクトル引数の usub.sat (usub.sat) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.usub.sat.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %a, <4 x i32> %b)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.fshl.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.fshl.v16i32 (<16 x i32> <left_op>, <16 x i32> <middle_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.fshl.nxv4i32  (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <middle_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.fshl.v256i64 (<256 x i64> <left_op>, <256 x i64> <middle_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

3つの整数ベクトルの述語付き fshl。

引数:

最初の3つの引数と結果は、同じ整数のベクトル型を持ちます。4番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。5番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.fshl’ 組み込み関数は、各有効レーンで、第一、第二、および第三ベクトル引数の fshl (fshl) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.fshl.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.fshr.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <16 x i32>  @llvm.vp.fshr.v16i32 (<16 x i32> <left_op>, <16 x i32> <middle_op>, <16 x i32> <right_op>, <16 x i1> <mask>, i32 <vector_length>)
declare <vscale x 4 x i32>  @llvm.vp.fshr.nxv4i32  (<vscale x 4 x i32> <left_op>, <vscale x 4 x i32> <middle_op>, <vscale x 4 x i32> <right_op>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
declare <256 x i64>  @llvm.vp.fshr.v256i64 (<256 x i64> <left_op>, <256 x i64> <middle_op>, <256 x i64> <right_op>, <256 x i1> <mask>, i32 <vector_length>)
概要:

3つの整数ベクトルの述語付き fshr。

引数:

最初の3つの引数と結果は、同じ整数のベクトル型を持ちます。4番目の引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。5番目の引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.fshr’ 組み込み関数は、各有効レーンで、第一、第二、および第三ベクトル引数の fshr (fshr) を実行します。無効レーンでの結果は、poison value です。

例:
%r = call <4 x i32> @llvm.vp.fshr.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c, <4 x i1> %mask, i32 %evl)
;; For all lanes below %evl, %r is lane-wise equivalent to %also.r

%t = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c)
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison

llvm.vp.is.fpclass.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。

declare <vscale x 2 x i1> @llvm.vp.is.fpclass.nxv2f32(<vscale x 2 x float> <op>, i32 <test>, <vscale x 2 x i1> <mask>, i32 <vector_length>)
declare <2 x i1> @llvm.vp.is.fpclass.v2f16(<2 x half> <op>, i32 <test>, <2 x i1> <mask>, i32 <vector_length>)
概要:

述語付き llvm.is.fpclass llvm.is.fpclass

引数:

第一引数は浮動小数点ベクトルであり、結果型は第一引数と同じ数の要素を持つブール値のベクトルです。第二引数は、実行するテストを指定します llvm.is.fpclass。第三引数はベクトルマスクであり、結果ベクトル型と同じ数の要素を持ちます。第四引数は、演算の明示的なベクトル長です。

意味:

llvm.vp.is.fpclass’ 組み込み関数は、llvm.is.fpclass (llvm.is.fpclass) を実行します。

例:
%r = call <2 x i1> @llvm.vp.is.fpclass.v2f16(<2 x half> %x, i32 3, <2 x i1> %m, i32 %evl)
%t = call <vscale x 2 x i1> @llvm.vp.is.fpclass.nxv2f16(<vscale x 2 x half> %x, i32 3, <vscale x 2 x i1> %m, i32 %evl)

マスク付きベクトルロードおよびストア組み込み関数

LLVMは、述語付きベクトルロードおよびストア操作のための組み込み関数を提供します。述語はマスク引数によって指定され、マスク引数はベクトル要素ごとに1ビットを保持し、関連するベクトルレーンをオンまたはオフにします。「オフ」レーンに対応するメモリアドレスはアクセスされません。マスクのすべてのビットがオンの場合、組み込み関数は通常のベクトルロードまたはストアと同じです。すべてのビットがオフの場合、メモリにはアクセスされません。

llvm.masked.load.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。ロードされたデータは、任意の整数、浮動小数点、またはポインタデータ型のベクトルです。

declare <16 x float>  @llvm.masked.load.v16f32.p0(ptr <ptr>, i32 <alignment>, <16 x i1> <mask>, <16 x float> <passthru>)
declare <2 x double>  @llvm.masked.load.v2f64.p0(ptr <ptr>, i32 <alignment>, <2 x i1>  <mask>, <2 x double> <passthru>)
;; The data is a vector of pointers
declare <8 x ptr> @llvm.masked.load.v8p0.p0(ptr <ptr>, i32 <alignment>, <8 x i1> <mask>, <8 x ptr> <passthru>)
概要:

指定されたマスクに従って、メモリからベクトルを読み取ります。マスクは各ベクトルレーンに対して1ビットを保持し、マスクオフされたレーンへのメモリアクセスを防ぐために使用されます。結果ベクトルのマスクオフされたレーンは、 ‘passthru’ 引数の対応するレーンから取得されます。

引数:

最初の引数はロードのベースポインターです。2番目の引数はソースロケーションのアライメントです。これは2のべき乗の定数整数値でなければなりません。3番目の引数であるマスクは、戻り値の型と同じ数の要素を持つブール値のベクトルです。4番目の引数は、マスクオフされた結果のレーンを埋めるために使用されるパススルー値です。戻り値の型、ベースポインターの基になる型、および「passthru」引数の型は、同じベクトル型です。

セマンティクス:

llvm.masked.load」組み込み関数は、単一のIR操作で選択されたベクトル要素を条件付きで読み取るために設計されています。これは、ベクトルマスクされたロードをサポートするターゲットに役立ち、これらのターゲットで述語付き基本ブロックをベクトル化できます。他のターゲットは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、スカラーロード操作を保護する一連の分岐に変換するなどです。この操作の結果は、通常のベクトルロード命令に続いて、ロードされた値とパススルー値の間の「選択」と同等です。ただし、マスクオフされたレーンはアクセスされないことを除き、同じマスクで述語化されます。ベクトルのマスクオンレーンのみが割り当ての境界内にある必要があります(ただし、これらのすべてのレーンは同じ割り当ての境界内にある必要があります)。特に、この組み込み関数を使用すると、マスクオフされたレーンへのメモリアクセスで例外が発生するのを防ぎます。マスクオフされたレーンは、データ競合またはnoalias制約の目的でもアクセスされたとは見なされません。

%res = call <16 x float> @llvm.masked.load.v16f32.p0(ptr %ptr, i32 4, <16 x i1>%mask, <16 x float> %passthru)

;; The result of the two following instructions is identical aside from potential memory access exception
%loadlal = load <16 x float>, ptr %ptr, align 4
%res = select <16 x i1> %mask, <16 x float> %loadlal, <16 x float> %passthru

llvm.masked.store.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリに格納されるデータは、任意の整数、浮動小数点、またはポインターデータ型のベクトルです。

declare void @llvm.masked.store.v8i32.p0 (<8  x i32>   <value>, ptr <ptr>, i32 <alignment>, <8  x i1> <mask>)
declare void @llvm.masked.store.v16f32.p0(<16 x float> <value>, ptr <ptr>, i32 <alignment>, <16 x i1> <mask>)
;; The data is a vector of pointers
declare void @llvm.masked.store.v8p0.p0  (<8 x ptr>    <value>, ptr <ptr>, i32 <alignment>, <8 x i1> <mask>)
概要:

提供されたマスクに従って、メモリにベクトルを書き込みます。マスクは各ベクトルレーンに1ビットを保持し、マスクオフされたレーンへのメモリアクセスを防ぐために使用されます。

引数:

最初の引数は、メモリに書き込むベクトル値です。2番目の引数は、ストアのベースポインターであり、値引数と同じ基になる型を持ちます。3番目の引数は、宛先ロケーションのアライメントです。これは2のべき乗の定数整数値でなければなりません。4番目の引数であるマスクは、ブール値のベクトルです。マスクと値引数の型は、同じ数のベクトル要素を持つ必要があります。

セマンティクス:

llvm.masked.store」組み込み関数は、単一のIR操作で選択されたベクトル要素を条件付きで書き込むために設計されています。これは、ベクトルマスクされたストアをサポートするターゲットに役立ち、これらのターゲットで述語付き基本ブロックをベクトル化できます。他のターゲットは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、スカラーストア操作を保護する一連の分岐に変換するなどです。この操作の結果は、ロード-変更-ストアシーケンスと同等です。ただし、マスクオフされたレーンはアクセスされないことを除きます。ベクトルのマスクオンレーンのみが割り当ての境界内にある必要があります(ただし、これらのすべてのレーンは同じ割り当ての境界内にある必要があります)。特に、この組み込み関数を使用すると、マスクオフされたレーンへのメモリアクセスで例外が発生するのを防ぎます。マスクオフされたレーンは、データ競合またはnoalias制約の目的でもアクセスされたとは見なされません。

call void @llvm.masked.store.v16f32.p0(<16 x float> %value, ptr %ptr, i32 4,  <16 x i1> %mask)

;; The result of the following instructions is identical aside from potential data races and memory access exceptions
%oldval = load <16 x float>, ptr %ptr, align 4
%res = select <16 x i1> %mask, <16 x float> %value, <16 x float> %oldval
store <16 x float> %res, ptr %ptr, align 4

マスクされたベクトルギャザーおよびスキャッター組み込み関数

LLVMは、ベクトルギャザーおよびスキャッター操作の組み込み関数を提供します。これらはマスクされたベクトルロードおよびストアに似ていますが、連続したメモリアクセスではなく、任意のメモリアクセス用に設計されている点が異なります。ギャザーおよびスキャッターも、ベクトル要素ごとに1ビットを保持するマスク引数を使用し、関連するベクトルレーンをオンまたはオフにします。 「オフ」レーンに対応するメモリアドレスはアクセスされません。すべてのビットがオフの場合、メモリはアクセスされません。

llvm.masked.gather.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。ロードされたデータは、任意の整数、浮動小数点、またはポインターデータ型の複数のスカラー値を1つのベクトルに集めたものです。

declare <16 x float> @llvm.masked.gather.v16f32.v16p0(<16 x ptr> <ptrs>, i32 <alignment>, <16 x i1> <mask>, <16 x float> <passthru>)
declare <2 x double> @llvm.masked.gather.v2f64.v2p1(<2 x ptr addrspace(1)> <ptrs>, i32 <alignment>, <2 x i1>  <mask>, <2 x double> <passthru>)
declare <8 x ptr> @llvm.masked.gather.v8p0.v8p0(<8 x ptr> <ptrs>, i32 <alignment>, <8 x i1>  <mask>, <8 x ptr> <passthru>)
概要:

任意のアドレスのメモリロケーションからスカラー値を読み取り、それらを1つのベクトルに集めます。メモリロケーションは、ポインターのベクトル「ptrs」で提供されます。メモリには、提供されたマスクに従ってアクセスされます。マスクは各ベクトルレーンに1ビットを保持し、マスクオフされたレーンへのメモリアクセスを防ぐために使用されます。結果ベクトルのマスクオフされたレーンは、「passthru」引数の対応するレーンから取得されます。

引数:

最初の引数は、読み取るすべてのメモリアドレスを保持するポインターのベクトルです。2番目の引数は、ソースアドレスのアライメントです。これは0または2のべき乗の定数整数値でなければなりません。3番目の引数であるマスクは、戻り値の型と同じ数の要素を持つブール値のベクトルです。4番目の引数は、マスクオフされた結果のレーンを埋めるために使用されるパススルー値です。戻り値の型、ポインターのベクトルの基になる型、および「passthru」引数の型は、同じベクトル型です。

セマンティクス:

llvm.masked.gather」組み込み関数は、単一のIR操作で任意のアドレスのメモリロケーションから複数のスカラー値を条件付きで読み取るために設計されています。これは、ベクトルマスクされたギャザーをサポートするターゲットに役立ち、データと制御の分岐を持つ基本ブロックをベクトル化できます。他のターゲットは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、一連のスカラーロード操作に変換するなどです。この操作のセマンティクスは、条件付きスカラーロードのシーケンスで、ロードされたすべての値を1つのベクトルに集めるのと同等です。マスクは特定のレーンへのメモリアクセスを制限し、述語付き基本ブロックのベクトル化を容易にします。

%res = call <4 x double> @llvm.masked.gather.v4f64.v4p0(<4 x ptr> %ptrs, i32 8, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x double> poison)

;; The gather with all-true mask is equivalent to the following instruction sequence
%ptr0 = extractelement <4 x ptr> %ptrs, i32 0
%ptr1 = extractelement <4 x ptr> %ptrs, i32 1
%ptr2 = extractelement <4 x ptr> %ptrs, i32 2
%ptr3 = extractelement <4 x ptr> %ptrs, i32 3

%val0 = load double, ptr %ptr0, align 8
%val1 = load double, ptr %ptr1, align 8
%val2 = load double, ptr %ptr2, align 8
%val3 = load double, ptr %ptr3, align 8

%vec0    = insertelement <4 x double> poison, %val0, 0
%vec01   = insertelement <4 x double> %vec0, %val1, 1
%vec012  = insertelement <4 x double> %vec01, %val2, 2
%vec0123 = insertelement <4 x double> %vec012, %val3, 3

llvm.masked.scatter.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリに格納されるデータは、任意の整数、浮動小数点、またはポインターデータ型のベクトルです。各ベクトル要素は、任意のメモリアドレスに格納されます。重複するアドレスでのスキャッターは、最下位要素から最上位要素に順序付けられていることが保証されています。

declare void @llvm.masked.scatter.v8i32.v8p0  (<8 x i32>    <value>, <8 x ptr>               <ptrs>, i32 <alignment>, <8 x i1>  <mask>)
declare void @llvm.masked.scatter.v16f32.v16p1(<16 x float> <value>, <16 x ptr addrspace(1)> <ptrs>, i32 <alignment>, <16 x i1> <mask>)
declare void @llvm.masked.scatter.v4p0.v4p0   (<4 x ptr>    <value>, <4 x ptr>               <ptrs>, i32 <alignment>, <4 x i1>  <mask>)
概要:

値ベクトルから対応するメモリアドレスに各要素を書き込みます。メモリアドレスは、ポインターのベクトルとして表されます。書き込みは、提供されたマスクに従って行われます。マスクは各ベクトルレーンに1ビットを保持し、マスクオフされたレーンへのメモリアクセスを防ぐために使用されます。

引数:

最初の引数は、メモリに書き込むベクトル値です。2番目の引数は、値要素を格納する場所を指すポインターのベクトルです。値引数と同じ基になる型を持ちます。3番目の引数は、宛先アドレスのアライメントです。これは0または2のべき乗の定数整数値でなければなりません。4番目の引数であるマスクは、ブール値のベクトルです。マスクと値引数の型は、同じ数のベクトル要素を持つ必要があります。

セマンティクス:

llvm.masked.scatter」組み込み関数は、単一のIR操作で選択されたベクトル要素を任意のメモリアドレスに書き込むために設計されています。操作は、マスクのすべてのビットがオンになっていない場合、条件付きになる場合があります。これは、ベクトルマスクされたスキャッターをサポートするターゲットに役立ち、データと制御の分岐を持つ基本ブロックをベクトル化できます。他のターゲットは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、スカラーストア操作を保護する一連の分岐に変換するなどです。

;; This instruction unconditionally stores data vector in multiple addresses
call @llvm.masked.scatter.v8i32.v8p0(<8 x i32> %value, <8 x ptr> %ptrs, i32 4,  <8 x i1>  <true, true, .. true>)

;; It is equivalent to a list of scalar stores
%val0 = extractelement <8 x i32> %value, i32 0
%val1 = extractelement <8 x i32> %value, i32 1
..
%val7 = extractelement <8 x i32> %value, i32 7
%ptr0 = extractelement <8 x ptr> %ptrs, i32 0
%ptr1 = extractelement <8 x ptr> %ptrs, i32 1
..
%ptr7 = extractelement <8 x ptr> %ptrs, i32 7
;; Note: the order of the following stores is important when they overlap:
store i32 %val0, ptr %ptr0, align 4
store i32 %val1, ptr %ptr1, align 4
..
store i32 %val7, ptr %ptr7, align 4

マスクされたベクトル拡張ロードおよび圧縮ストア組み込み関数

LLVMは、拡張ロードおよび圧縮ストア操作の組み込み関数を提供します。マスクに従ってベクトルから選択されたデータは、連続したメモリアドレス(圧縮ストア)に格納され、その逆(拡張ロード)も行われます。これらの操作は、事実上「if (cond.i) a[j++] = v.i」および「if (cond.i) v.i = a[j++]」パターンにマッピングされます。マスクが「1」ビットで始まり、その後に「0」ビットが続く場合、これらの操作はllvm.masked.storeおよびllvm.masked.loadと同じであることに注意してください。

llvm.masked.expandload.*」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。整数、浮動小数点、またはポインターデータ型のいくつかの値が、連続したメモリアドレスからロードされ、マスクに従ってベクトルの要素に格納されます。

declare <16 x float>  @llvm.masked.expandload.v16f32 (ptr <ptr>, <16 x i1> <mask>, <16 x float> <passthru>)
declare <2 x i64>     @llvm.masked.expandload.v2i64 (ptr <ptr>, <2 x i1>  <mask>, <2 x i64> <passthru>)
概要:

ptr」で提供されるメモリロケーションから一連のスカラー値を順番に読み取り、ベクトルに展開します。「mask」は各ベクトルレーンに1ビットを保持します。メモリから読み取られる要素の数は、マスク内の「1」ビットの数と同じです。ロードされた要素は、マスク内の「1」と「0」のビットのシーケンスに従って、宛先ベクトルに配置されます。たとえば、マスクベクトルが「10010001」の場合、「expandload」はメモリアドレスptr、ptr+1、ptr+2から3つの値を読み取り、それぞれレーン0、3、7に配置します。マスクオフされたレーンは、「passthru」引数の対応するレーンからの要素で埋められます。

引数:

最初の引数は、ロードのベースポインターです。これは、返されるベクトルの要素と同じ基になる型を持ちます。2番目の引数であるマスクは、戻り値の型と同じ数の要素を持つブール値のベクトルです。3番目の引数は、マスクオフされた結果のレーンを埋めるために使用されるパススルー値です。戻り値の型と「passthru」引数の型は、同じベクトル型です。

alignパラメーター属性は、最初の引数に指定できます。ポインターのアライメントはデフォルトで1です。

セマンティクス:

llvm.masked.expandload」組み込み関数は、隣接するメモリアドレスから複数のスカラー値を、隣接しない可能性のあるベクトルレーンに読み込むために設計されています。これは、ベクトル拡張ロードをサポートするターゲットに役立ち、次の例のように反復間の依存関係を持つループをベクトル化できます。

// In this loop we load from B and spread the elements into array A.
double *A, B; int *C;
for (int i = 0; i < size; ++i) {
  if (C[i] != 0)
    A[i] = B[j++];
}
; Load several elements from array B and expand them in a vector.
; The number of loaded elements is equal to the number of '1' elements in the Mask.
%Tmp = call <8 x double> @llvm.masked.expandload.v8f64(ptr %Bptr, <8 x i1> %Mask, <8 x double> poison)
; Store the result in A
call void @llvm.masked.store.v8f64.p0(<8 x double> %Tmp, ptr %Aptr, i32 8, <8 x i1> %Mask)

; %Bptr should be increased on each iteration according to the number of '1' elements in the Mask.
%MaskI = bitcast <8 x i1> %Mask to i8
%MaskIPopcnt = call i8 @llvm.ctpop.i8(i8 %MaskI)
%MaskI64 = zext i8 %MaskIPopcnt to i64
%BNextInd = add i64 %BInd, %MaskI64

他のターゲットは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、条件付きスカラーロード操作とシャッフルの一連に変換するなどです。すべてのマスク要素が「1」の場合、組み込み関数の動作は通常のマスクされていないベクトルロードと同じです。

llvm.masked.compressstore.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。整数型、浮動小数点型、またはポインター型の複数のスカラ値が、入力ベクトルから収集され、隣接するメモリアドレスに格納されます。マスクは、ベクトルからどの要素を収集するかを定義します。

declare void @llvm.masked.compressstore.v8i32  (<8  x i32>   <value>, ptr <ptr>, <8  x i1> <mask>)
declare void @llvm.masked.compressstore.v16f32 (<16 x float> <value>, ptr <ptr>, <16 x i1> <mask>)
概要:

入力ベクトル ‘value’ から、‘mask’ に従って要素を選択します。選択されたすべての要素は、アドレス ‘ptr’ を開始アドレスとして、小さいアドレスから大きいアドレスへ隣接するメモリアドレスに書き込まれます。マスクはベクトルレーンごとに1ビットを保持し、格納する要素を選択するために使用されます。格納される要素の数は、マスクのアクティブなビット数と同じです。

引数:

最初の引数は入力ベクトルで、ここから要素が収集されメモリに書き込まれます。2番目の引数は格納のベースポインターで、入力ベクトル引数の要素と同じ基本型を持ちます。3番目の引数はマスクで、ブール値のベクトルです。マスクと入力ベクトルは、同じ数のベクトル要素を持つ必要があります。

align パラメータ属性は、2番目の引数に指定できます。ポインターのアライメントはデフォルトで1です。

セマンティクス:

llvm.masked.compressstore’ 組み込み関数は、メモリ内のデータを圧縮するために設計されています。これにより、ベクトルの隣接していない可能性のあるレーンから要素を収集し、1つのIR操作でメモリに連続して格納できます。これは、圧縮ストア操作をサポートするターゲットに役立ち、次の例のように反復間の依存関係を持つループをベクトル化できます。

// In this loop we load elements from A and store them consecutively in B
double *A, B; int *C;
for (int i = 0; i < size; ++i) {
  if (C[i] != 0)
    B[j++] = A[i]
}
; Load elements from A.
%Tmp = call <8 x double> @llvm.masked.load.v8f64.p0(ptr %Aptr, i32 8, <8 x i1> %Mask, <8 x double> poison)
; Store all selected elements consecutively in array B
call <void> @llvm.masked.compressstore.v8f64(<8 x double> %Tmp, ptr %Bptr, <8 x i1> %Mask)

; %Bptr should be increased on each iteration according to the number of '1' elements in the Mask.
%MaskI = bitcast <8 x i1> %Mask to i8
%MaskIPopcnt = call i8 @llvm.ctpop.i8(i8 %MaskI)
%MaskI64 = zext i8 %MaskIPopcnt to i64
%BNextInd = add i64 %BInd, %MaskI64

他のターゲットでは、この組み込み関数を異なる方法でサポートする場合があります。たとえば、スカラストア操作をガードする一連の分岐に変換することなどがあります。

メモリ使用マーカー

このクラスの組み込み関数は、メモリオブジェクトの寿命と、変数が不変である範囲に関する情報を提供します。

llvm.lifetime.start’ 組み込み関数

構文:
declare void @llvm.lifetime.start(i64 <size>, ptr nocapture <ptr>)
概要:

llvm.lifetime.start’ 組み込み関数は、メモリオブジェクトの寿命の開始を指定します。

引数:

最初の引数はオブジェクトのサイズを表す定数整数であり、可変サイズの場合は-1です。2番目の引数はオブジェクトへのポインターです。

セマンティクス:

ptr がスタック割り当てのオブジェクトであり、オブジェクトの最初のバイトを指している場合、オブジェクトは最初は無効としてマークされます。ptr がスタック割り当てのオブジェクトであると最適化パイプラインで使用されるスタック彩色アルゴリズムが判断できない場合は、ptr は非スタック割り当てのオブジェクトと見なされます。

llvm.lifetime.start’ の後、ptr が指すスタックオブジェクトは有効としてマークされ、初期化されていない値を持っています。スタックオブジェクトは、allocaへのllvm.lifetime.endが実行されるか、関数が戻るときに無効としてマークされます。

llvm.lifetime.end が呼び出された後、スタックオブジェクトで ‘llvm.lifetime.start’ を再度呼び出すことができます。2回目の ‘llvm.lifetime.start’ 呼び出しは、オブジェクトを有効としてマークしますが、オブジェクトのアドレスは変更しません。

ptr が非スタック割り当てのオブジェクトであるか、オブジェクトの最初のバイトを指していないか、またはすでに有効なスタックオブジェクトである場合、オブジェクトのすべてのバイトを単に poison で埋めます。

llvm.lifetime.end’ 組み込み関数

構文:
declare void @llvm.lifetime.end(i64 <size>, ptr nocapture <ptr>)
概要:

llvm.lifetime.end’ 組み込み関数は、メモリオブジェクトの寿命の終了を指定します。

引数:

最初の引数はオブジェクトのサイズを表す定数整数であり、可変サイズの場合は-1です。2番目の引数はオブジェクトへのポインターです。

セマンティクス:

ptr がスタック割り当てのオブジェクトであり、オブジェクトの最初のバイトを指している場合、オブジェクトは無効になります。ptr がスタック割り当てのオブジェクトであると最適化パイプラインで使用されるスタック彩色アルゴリズムが判断できない場合は、ptr は非スタック割り当てのオブジェクトと見なされます。

すでに無効になっているallocaで llvm.lifetime.end を呼び出すことは、何もしない操作です。

ptr が非スタック割り当てのオブジェクトであるか、オブジェクトの最初のバイトを指していない場合、オブジェクトのすべてのバイトを単に poison で埋めることと同じです。

llvm.invariant.start’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリオブジェクトは任意のアドレス空間に属することができます。

declare ptr @llvm.invariant.start.p0(i64 <size>, ptr nocapture <ptr>)
概要:

llvm.invariant.start’ 組み込み関数は、メモリオブジェクトの内容が変更されないことを指定します。

引数:

最初の引数はオブジェクトのサイズを表す定数整数であり、可変サイズの場合は-1です。2番目の引数はオブジェクトへのポインターです。

セマンティクス:

この組み込み関数は、戻り値を使用する llvm.invariant.end まで、参照されるメモリ位置が定数であり、変更されないことを示します。

llvm.invariant.end’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリオブジェクトは任意のアドレス空間に属することができます。

declare void @llvm.invariant.end.p0(ptr <start>, i64 <size>, ptr nocapture <ptr>)
概要:

llvm.invariant.end’ 組み込み関数は、メモリオブジェクトの内容が可変であることを指定します。

引数:

最初の引数は、一致する llvm.invariant.start 組み込み関数です。2番目の引数はオブジェクトのサイズを表す定数整数であり、可変サイズの場合は-1であり、3番目の引数はオブジェクトへのポインターです。

セマンティクス:

この組み込み関数は、メモリが再び可変であることを示します。

llvm.launder.invariant.group’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリオブジェクトは任意のアドレス空間に属することができます。返されるポインターは、引数と同じアドレス空間に属している必要があります。

declare ptr @llvm.launder.invariant.group.p0(ptr <ptr>)
概要:

llvm.launder.invariant.group’ 組み込み関数は、invariant.group メタデータによって確立された不変条件が保持されなくなった場合に、新しい不変グループ情報を運ぶ新しいポインター値を取得するために使用できます。これは実験的な組み込み関数であり、そのセマンティクスは将来変更される可能性があります。

引数:

llvm.launder.invariant.group は、メモリへのポインターである1つの引数のみを受け取ります。

セマンティクス:

引数をエイリアスするが、load/store invariant.group メタデータの目的では異なるものと見なされる別のポインターを返します。アクセス可能なメモリは読み取らず、実行を推測できます。

llvm.strip.invariant.group’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。メモリオブジェクトは任意のアドレス空間に属することができます。返されるポインターは、引数と同じアドレス空間に属している必要があります。

declare ptr @llvm.strip.invariant.group.p0(ptr <ptr>)
概要:

llvm.strip.invariant.group’ 組み込み関数は、invariant.group メタデータによって確立された不変条件が保持されなくなった場合に、不変情報を持たない新しいポインター値を取得するために使用できます。これは実験的な組み込み関数であり、そのセマンティクスは将来変更される可能性があります。

引数:

llvm.strip.invariant.group は、メモリへのポインターである1つの引数のみを受け取ります。

セマンティクス:

引数をエイリアスするが、関連付けられた invariant.group メタデータを持たない別のポインターを返します。メモリは読み取らず、推測できます。

制約付き浮動小数点組み込み関数

これらの組み込み関数は、特定の丸めモードまたは浮動小数点例外の動作が必要な場合に、浮動小数点演算の特別な処理を提供するために使用されます。デフォルトでは、LLVM最適化パスは、丸めモードが最近傍への丸めであり、浮動小数点例外が監視されないと想定します。制約付きFP組み込み関数は、デフォルト以外の丸めモードをサポートし、デフォルトの動作が使用されている場合にLLVMのFPコードを最適化する機能を損なうことなく、例外の動作を正確に保持するために使用されます。

関数内でFP演算が制約されている場合、それらはすべて制約されている必要があります。これは、正しいLLVM IRのために必要です。コードを移動する最適化は、制約付き演算と通常の演算を混在させると、コンパイルミスを引き起こす可能性があります。制約付き演算と制約の少ない演算を混在させる正しい方法は、丸めモードと例外処理メタデータを使用して、制約付き組み込み関数にLLVMのデフォルトの動作があるようにマークすることです。

これらの組み込み関数はそれぞれ、通常の浮動小数点演算に対応しています。データ引数と戻り値は、対応するFP演算と同じです。

丸めモード引数は、定数値を変換するときに、オプティマイザーがどのような仮定を行うことができるかを指定するメタデータ文字列です。一部の制約付きFP組み込み関数では、この引数が省略されます。組み込み関数で必要な場合、この引数は次のいずれかの文字列である必要があります。

"round.dynamic"
"round.tonearest"
"round.downward"
"round.upward"
"round.towardzero"
"round.tonearestaway"

この引数が「round.dynamic」の場合、最適化パスは丸めモードが不明であり、実行時に変更される可能性があると想定する必要があります。この場合、丸めモードに依存する変換は実行できません。

丸めモード引数のその他の可能な値は、同様に名前が付けられたIEEE丸めモードに対応します。引数がこれらの値のいずれかである場合、最適化パスは、指定された丸めモードと一致する限り、変換を実行できます。

たとえば、丸めモードが「round.downward」または「round.dynamic」の場合、「x-0」->「x」は有効な変換ではありません。「x」の値が+0の場合、「x-0」は下方への丸めを行うと「-0」と評価される必要があるためです。ただし、この変換は他のすべての丸めモードでは合法です。

「round.dynamic」以外の値の場合、最適化パスは、実際の実行時丸めモード(ターゲット固有の方法で定義)が指定された丸めモードと一致すると想定できますが、これは保証されません。実行時の実際の丸めモードと一致しない特定の非動的丸めモードを使用すると、未定義の動作になります。

例外動作引数は、組み込み関数に必要な浮動小数点例外セマンティクスを記述するメタデータ文字列です。この引数は、次のいずれかの文字列である必要があります。

"fpexcept.ignore"
"fpexcept.maytrap"
"fpexcept.strict"

この引数が「fpexcept.ignore」の場合、最適化パスは、例外ステータスフラグが読み取られず、浮動小数点例外がマスクされると想定できます。これにより、元のコードの例外セマンティクスを変更する可能性のある変換を実行できます。たとえば、FP演算は、この場合投機的に実行できますが、この引数の他の可能な値のいずれに対しても実行してはなりません。

例外動作引数が「fpexcept.maytrap」の場合、最適化パスは、元のコードでは発生しなかった例外を引き起こす可能性のある変換(FP演算の投機的実行など)を回避する必要がありますが、パスは元のコードによって暗示されるすべての例外を保持する必要はありません。たとえば、例外は定数畳み込みによって潜在的に隠される可能性があります。

例外動作引数が「fpexcept.strict」の場合、すべての変換は、元のコードの浮動小数点例外セマンティクスを厳密に保持する必要があります。元のコードによって発生した可能性のあるFP例外は、変換されたコードによって発生する必要があり、変換されたコードは、元のコードによって発生しなかった可能性のあるFP例外を発生させてはなりません。これは、コンパイルされるコードがFP例外ステータスフラグを読み取る場合に使用される例外動作引数ですが、このモードはFP例外のマスクを解除するコードでも使用できます。

浮動小数点例外の数と順序は保証されません。たとえば、それぞれ例外を発生させる可能性のある一連のFP演算は、各固有の例外を1回だけ発生させる単一の命令にベクトル化される場合があります。

制約付き組み込み関数が正しく機能するには、適切な関数属性の使用が必要です。

制約付き浮動小数点組み込み関数を使用する関数で行われるすべての関数呼び出しは、呼び出し命令または呼び出される関数の宣言または定義のいずれかにstrictfp属性を持っている必要があります。

制約付き浮動小数点組み込み関数を使用するすべての関数定義は、strictfp属性を持っている必要があります。

llvm.experimental.constrained.fadd」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fadd(<type> <op1>, <type> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fadd」組み込み関数は、2つの引数の合計を返します。

引数:

llvm.experimental.constrained.fadd」組み込み関数の最初の2つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は、同一の型を持っている必要があります。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

セマンティクス:

生成される値は、2つの値引数の浮動小数点和であり、引数と同じ型を持ちます。

llvm.experimental.constrained.fsub」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fsub(<type> <op1>, <type> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fsub」組み込み関数は、2つの引数の差を返します。

引数:

llvm.experimental.constrained.fsub」組み込み関数の最初の2つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は、同一の型を持っている必要があります。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

セマンティクス:

生成される値は、2つの値引数の浮動小数点差であり、引数と同じ型を持ちます。

llvm.experimental.constrained.fmul」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fmul(<type> <op1>, <type> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fmul」組み込み関数は、2つの引数の積を返します。

引数:

llvm.experimental.constrained.fmul」組み込み関数の最初の2つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は、同一の型を持っている必要があります。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

セマンティクス:

生成される値は、2つの値引数の浮動小数点積であり、引数と同じ型を持ちます。

llvm.experimental.constrained.fdiv」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fdiv(<type> <op1>, <type> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fdiv」組み込み関数は、2つの引数の商を返します。

引数:

llvm.experimental.constrained.fdiv」組み込み関数の最初の2つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は、同一の型を持っている必要があります。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

セマンティクス:

生成される値は、2つの値引数の浮動小数点商であり、引数と同じ型を持ちます。

llvm.experimental.constrained.frem」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.frem(<type> <op1>, <type> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.frem」組み込み関数は、2つの引数の除算の剰余を返します。

引数:

llvm.experimental.constrained.frem」組み込み関数の最初の2つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は、同一の型を持っている必要があります。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。fremの結果は決して丸められないため、丸めモード引数は効果がありませんが、この引数は他の制約付き浮動小数点組み込み関数との一貫性のために含まれています。

セマンティクス:

生成される値は、2つの値引数の除算による浮動小数点剰余であり、引数と同じ型を持ちます。剰余は被除数と同じ符号を持ちます。

llvm.experimental.constrained.fma」組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fma(<type> <op1>, <type> <op2>, <type> <op3>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fma’ 組み込み関数は、引数に対して FMA (Fused-Multiply-Add) 演算の結果を返します。

引数:

llvm.experimental.constrained.fma’ 組み込み関数の最初の 3 つの引数は、浮動小数点数または浮動小数点数値のベクトルである必要があります。すべての引数は同じ型である必要があります。

4 番目と 5 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

生成される結果は、最初の 2 つの引数の積に 3 番目の引数を加算したもので、無限の精度で計算され、ターゲットの精度に丸められます。

llvm.experimental.constrained.fptoui’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.fptoui(<type> <value>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fptoui’ 組み込み関数は、浮動小数点を型 ty2 の符号なし整数相当の値に変換します。

引数:

llvm.experimental.constrained.fptoui’ 組み込み関数の最初の引数は、浮動小数点または浮動小数点値のベクトルである必要があります。

2 番目の引数は、上記の例外動作を指定します。

意味:

生成される結果は、浮動小数点引数から変換された符号なし整数です。値は切り捨てられるため、ゼロに向かって丸められます。

llvm.experimental.constrained.fptosi’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.fptosi(<type> <value>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fptosi’ 組み込み関数は、浮動小数点を型 ty2 に変換します。

引数:

llvm.experimental.constrained.fptosi’ 組み込み関数の最初の引数は、浮動小数点または浮動小数点値のベクトルである必要があります。

2 番目の引数は、上記の例外動作を指定します。

意味:

生成される結果は、浮動小数点引数から変換された符号付き整数です。値は切り捨てられるため、ゼロに向かって丸められます。

llvm.experimental.constrained.uitofp’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.uitofp(<type> <value>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.uitofp’ 組み込み関数は、符号なし整数を型 ty2 の浮動小数点数に変換します。

引数:

llvm.experimental.constrained.uitofp’ 組み込み関数の最初の引数は、整数または整数値のベクトルである必要があります。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

丸めが必要な場合、不正確な浮動小数点例外が発生します。生成される結果は、入力整数引数から変換された浮動小数点値です。

llvm.experimental.constrained.sitofp’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.sitofp(<type> <value>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.sitofp’ 組み込み関数は、符号付き整数を型 ty2 の浮動小数点数に変換します。

引数:

llvm.experimental.constrained.sitofp’ 組み込み関数の最初の引数は、整数または整数値のベクトルである必要があります。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

丸めが必要な場合、不正確な浮動小数点例外が発生します。生成される結果は、入力整数引数から変換された浮動小数点値です。

llvm.experimental.constrained.fptrunc’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.fptrunc(<type> <value>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fptrunc’ 組み込み関数は、を型 ty2 に切り捨てます。

引数:

llvm.experimental.constrained.fptrunc’ 組み込み関数の最初の引数は、浮動小数点または浮動小数点値のベクトルである必要があります。この引数は、結果よりもサイズが大きい必要があります。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

生成される結果は、引数よりもサイズが小さくなるように切り捨てられた浮動小数点値です。

llvm.experimental.constrained.fpext’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.fpext(<type> <value>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.fpext’ 組み込み関数は、浮動小数点をより大きな浮動小数点値に拡張します。

引数:

llvm.experimental.constrained.fpext’ 組み込み関数の最初の引数は、浮動小数点または浮動小数点値のベクトルである必要があります。この引数は、結果よりもサイズが小さい必要があります。

2 番目の引数は、上記の例外動作を指定します。

意味:

生成される結果は、引数よりもサイズが大きくなるように拡張された浮動小数点値です。fpext 命令に適用されるすべての制限は、この組み込み関数にも適用されます。

llvm.experimental.constrained.fcmp’ および ‘llvm.experimental.constrained.fcmps’ 組み込み関数

構文:
declare <ty2>
@llvm.experimental.constrained.fcmp(<type> <op1>, <type> <op2>,
                                    metadata <condition code>,
                                    metadata <exception behavior>)
declare <ty2>
@llvm.experimental.constrained.fcmps(<type> <op1>, <type> <op2>,
                                     metadata <condition code>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.fcmp’ および ‘llvm.experimental.constrained.fcmps’ 組み込み関数は、引数の比較に基づいて、ブール値またはブール値のベクトルを返します。

引数が浮動小数点スカラーである場合、結果の型はブール値 (i1) になります。

引数が浮動小数点ベクトルの場合、結果の型は、比較される引数と同じ数の要素を持つブール値のベクトルになります。

llvm.experimental.constrained.fcmp’ 組み込み関数は、静かな比較演算を実行しますが、‘llvm.experimental.constrained.fcmps’ 組み込み関数は、シグナリング比較演算を実行します。

引数:

llvm.experimental.constrained.fcmp’ および ‘llvm.experimental.constrained.fcmps’ 組み込み関数の最初の 2 つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。両方の引数は同じ型である必要があります。

3 番目の引数は、実行する比較の種類を示す条件コードです。次のいずれかの値を持つメタデータ文字列である必要があります。

  • oeq”: 順序付けられ、等しい

  • ogt”: 順序付けられ、より大きい

  • oge”: 順序付けられ、以上

  • olt”: 順序付けられ、より小さい

  • ole”: 順序付けられ、以下

  • one”: 順序付けられ、等しくない

  • ord”: 順序付けられている (NaN がない)

  • ueq”: 順序付けられていないか、等しい

  • ugt”: 順序付けられていないか、より大きい

  • uge”: 順序付けられていないか、以上

  • ult”: 順序付けられていないか、より小さい

  • ule”: 順序付けられていないか、以下

  • une”: 順序付けられていないか、等しくない

  • uno”: 順序付けられていない (どちらかの NaN)

順序付けられているとは、どちらの引数も NAN でないことを意味し、順序付けられていないとは、どちらかの引数が NAN である可能性があることを意味します。

4 番目の引数は、上記の例外動作を指定します。

意味:

op1op2 は、3番目の引数として与えられた条件コードに従って比較されます。引数がベクトルの場合、ベクトルは要素ごとに比較されます。実行される各比較は、常に i1 の結果を生成します。以下にその詳細を示します。

  • oeq”: 両方の引数が NAN でなく、op1op2 と等しい場合に true を生成します。

  • ogt”: 両方の引数が NAN でなく、op1op2 より大きい場合に true を生成します。

  • oge”: 両方の引数が NAN でなく、op1op2 以上である場合に true を生成します。

  • olt”: 両方の引数が NAN でなく、op1op2 より小さい場合に true を生成します。

  • ole”: 両方の引数が NAN でなく、op1op2 以下である場合に true を生成します。

  • one”: 両方の引数が NAN でなく、op1op2 と等しくない場合に true を生成します。

  • ord”: 両方の引数が NAN でない場合に true を生成します。

  • ueq”: いずれかの引数が NAN であるか、または op1op2 と等しい場合に true を生成します。

  • ugt”: いずれかの引数が NAN であるか、または op1op2 より大きい場合に true を生成します。

  • uge”: いずれかの引数が NAN であるか、または op1op2 以上である場合に true を生成します。

  • ult”: いずれかの引数が NAN であるか、または op1op2 より小さい場合に true を生成します。

  • ule”: いずれかの引数が NAN であるか、または op1op2 以下である場合に true を生成します。

  • une”: いずれかの引数が NAN であるか、または op1op2 と等しくない場合に true を生成します。

  • uno”: いずれかの引数が NAN である場合に true を生成します。

llvm.experimental.constrained.fcmp’ によって実行される静かな比較演算は、いずれかの引数が SNAN の場合にのみ例外を発生させます。‘llvm.experimental.constrained.fcmps’ によって実行されるシグナリング比較演算は、いずれかの引数が NAN (QNAN または SNAN) の場合に例外を発生させます。このような例外が発生しても結果の生成が妨げられるわけではありません (例えば、例外は単にフラグを設定するだけの場合があります)。したがって、順序付けられた比較と順序付けられていない比較の区別は、‘llvm.experimental.constrained.fcmps’ 組み込み関数にも関連します。

llvm.experimental.constrained.fmuladd’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.fmuladd(<type> <op1>, <type> <op2>,
                                       <type> <op3>,
                                       metadata <rounding mode>,
                                       metadata <exception behavior>)
概要:

llvm.experimental.constrained.fmuladd’ 組み込み関数は、コードジェネレータが以下のことを判断した場合に、融合できる乗算加算式を表します。(a) ターゲット命令セットが融合演算をサポートしている場合、および (b) 融合演算が同等の個別の乗算命令と加算命令のペアよりも効率的である場合。

引数:

llvm.experimental.constrained.fmuladd’ 組み込み関数の最初の 3 つの引数は、浮動小数点または浮動小数点値のベクトルである必要があります。3 つの引数はすべて同じ型である必要があります。

4 番目と 5 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

%0 = call float @llvm.experimental.constrained.fmuladd.f32(%a, %b, %c,
                                                           metadata <rounding mode>,
                                                           metadata <exception behavior>)

次の式と同等です。

%0 = call float @llvm.experimental.constrained.fmul.f32(%a, %b,
                                                        metadata <rounding mode>,
                                                        metadata <exception behavior>)
%1 = call float @llvm.experimental.constrained.fadd.f32(%0, %c,
                                                        metadata <rounding mode>,
                                                        metadata <exception behavior>)

ただし、乗算と加算のステップ間で丸めが行われるかどうかは指定されていません。ターゲットプラットフォームがサポートしていても、融合が保証されるわけではありません。融合乗算加算が必要な場合は、代わりに、対応する llvm.experimental.constrained.fma 組み込み関数を使用する必要があります。これは、‘llvm.experimental.constrained.fma.*’ と同様に、errno を設定しません。

制約付き libm 相当の組み込み関数

上記で説明した制約付き組み込み関数である基本的な浮動小数点演算に加えて、対応する libm 関数と同等の動作を提供するさまざまな演算の制約付きバージョンがあります。これらの組み込み関数を使用すると、丸めモードと例外動作に関するこれらの演算の正確な動作を制御できます。

基本的な制約付き浮動小数点組み込み関数と同様に、丸めモードと例外動作の引数は、オプティマイザの動作のみを制御します。実行時の浮動小数点環境は変更しません。

llvm.experimental.constrained.sqrt’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.sqrt(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.sqrt’ 組み込み関数は、指定された値の平方根を返し、libm ‘sqrt’ 関数と同じ値を返しますが、errno を設定しません。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定された値の非負の平方根を返します。値が負のゼロより小さい場合、浮動小数点例外が発生し、戻り値はアーキテクチャ固有の値になります。

llvm.experimental.constrained.pow’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.pow(<type> <op1>, <type> <op2>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.pow’ 組み込み関数は、最初の引数を2番目の引数で指定された (正または負の) べき乗に上げた値を返します。

引数:

最初の 2 つの引数と戻り値は、同じ型の浮動小数点数です。2 番目の引数は、最初の引数をべき乗するべき指数を指定します。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

意味:

この関数は、最初の値を2番目のべき乗に上げた値を返し、libm pow 関数と同じ値を返し、エラー状態を同じ方法で処理します。

llvm.experimental.constrained.powi’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.powi(<type> <op1>, i32 <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.powi’ 組み込み関数は、最初の引数を2番目の引数で指定された (正または負の) べき乗に上げた値を返します。乗算の評価順序は定義されていません。浮動小数点型のベクトルが使用されている場合、2 番目の引数はスカラー整数値のままです。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。2 番目の引数は、最初の引数をべき乗するべき指数を指定する 32 ビット符号付き整数です。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

意味:

この関数は、丸め演算の順序が指定されていない状態で、最初の値を2番目の累乗で累乗した値を返します。

llvm.experimental.constrained.ldexp’ 組み込み関数

構文:
declare <type0>
@llvm.experimental.constrained.ldexp(<type0> <op1>, <type1> <op2>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.ldexp’ は ldexp 関数を実行します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数または浮動小数点数のベクトルです。2番目の引数は、要素数が同じ整数です。

3番目と4番目の引数は、上記のように丸めモードと例外動作を指定します。

意味:

この関数は、最初の引数に2のべき乗(2番目の引数)を掛けます。最初の引数がNaNまたは無限大の場合、同じ値が返されます。結果がアンダーフローする場合は、同じ符号のゼロが返されます。結果がオーバーフローする場合は、同じ符号の無限大が結果になります。

llvm.experimental.constrained.sin’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.sin(<type> <op1>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.sin’ 組み込み関数は、最初の引数の正弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定された引数の正弦を返し、libmのsin関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.cos’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.cos(<type> <op1>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.cos’ 組み込み関数は、最初の引数の余弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定された引数の余弦を返し、libmのcos関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.tan’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.tan(<type> <op1>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.tan’ 組み込み関数は、最初の引数の正接を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定された引数の正接を返し、libmのtan関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.asin’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.asin(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.asin’ 組み込み関数は、最初のオペランドの逆正弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの逆正弦を返し、libmのasin関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.acos’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.acos(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.acos’ 組み込み関数は、最初のオペランドの逆余弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの逆余弦を返し、libmのacos関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.atan’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.atan(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.atan’ 組み込み関数は、最初のオペランドの逆正接を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの逆正接を返し、libmのatan関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.sinh’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.sinh(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.sinh’ 組み込み関数は、最初のオペランドの双曲線正弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの双曲線正弦を返し、libmのsinh関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.cosh’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.cosh(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.cosh’ 組み込み関数は、最初のオペランドの双曲線余弦を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの双曲線余弦を返し、libmのcosh関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.tanh’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.tanh(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.tanh’ 組み込み関数は、最初のオペランドの双曲線正接を返します。

引数:

最初の引数と戻り値の型は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、指定されたオペランドの双曲線正接を返し、libmのtanh関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.exp’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.exp(<type> <op1>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.exp’ 組み込み関数は、指定された値の自然指数を計算します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、libmのexp関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.exp2’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.exp2(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.exp2’ 組み込み関数は、指定された値の2を底とする指数を計算します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、libmのexp2関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.log’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.log(<type> <op1>,
                                   metadata <rounding mode>,
                                   metadata <exception behavior>)
概要:

llvm.experimental.constrained.log’ 組み込み関数は、指定された値の自然対数を計算します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、libmのlog関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.log10’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.log10(<type> <op1>,
                                     metadata <rounding mode>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.log10’ 組み込み関数は、指定された値の10を底とする対数を計算します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、libmのlog10関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.log2’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.log2(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.log2’ 組み込み関数は、指定された値の2を底とする対数を計算します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

意味:

この関数は、libmのlog2関数と同じ値を返し、エラー条件も同じように処理します。

llvm.experimental.constrained.rint’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.rint(<type> <op1>,
                                    metadata <rounding mode>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.rint’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。引数が整数でない場合、不正確な浮動小数点例外が発生する可能性があります。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

セマンティクス:

この関数は、libm の rint 関数と同じ値を返し、エラー条件も同様に処理します。丸めモードは、丸めモード引数によって記述されますが、決定されるわけではありません。実際の丸めモードは、実行時の浮動小数点環境によって決定されます。丸めモード引数は、コンパイラーへの情報提供のみを目的としています。

llvm.experimental.constrained.lrint’ 組み込み関数

構文:
declare <inttype>
@llvm.experimental.constrained.lrint(<fptype> <op1>,
                                     metadata <rounding mode>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.lrint’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。引数が整数でない場合は、不正確な浮動小数点例外が発生します。結果がサポートされている整数型に収まらないほど大きい場合は、無効な例外が発生し、この場合、結果は未定義になります。

引数:

最初の引数は浮動小数点数です。戻り値は整数型です。すべての型がすべてのターゲットでサポートされているわけではありません。サポートされている型は、llvm.lrint 組み込み関数および lrint libm 関数と同じです。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

セマンティクス:

この関数は、libm の lrint 関数と同じ値を返し、エラー条件も同様に処理します。

丸めモードは、丸めモード引数によって記述されますが、決定されるわけではありません。実際の丸めモードは、実行時の浮動小数点環境によって決定されます。丸めモード引数は、コンパイラーへの情報提供のみを目的としています。

実行時の浮動小数点環境がデフォルトの丸めモードを使用している場合、結果は llvm.lrint 組み込み関数と同じになります。

llvm.experimental.constrained.llrint’ 組み込み関数

構文:
declare <inttype>
@llvm.experimental.constrained.llrint(<fptype> <op1>,
                                      metadata <rounding mode>,
                                      metadata <exception behavior>)
概要:

llvm.experimental.constrained.llrint’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。引数が整数でない場合は、不正確な浮動小数点例外が発生します。結果がサポートされている整数型に収まらないほど大きい場合は、無効な例外が発生し、この場合、結果は未定義になります。

引数:

最初の引数は浮動小数点数です。戻り値は整数型です。すべての型がすべてのターゲットでサポートされているわけではありません。サポートされている型は、llvm.llrint 組み込み関数および llrint libm 関数と同じです。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

セマンティクス:

この関数は、libm の llrint 関数と同じ値を返し、エラー条件も同様に処理します。

丸めモードは、丸めモード引数によって記述されますが、決定されるわけではありません。実際の丸めモードは、実行時の浮動小数点環境によって決定されます。丸めモード引数は、コンパイラーへの情報提供のみを目的としています。

実行時の浮動小数点環境がデフォルトの丸めモードを使用している場合、結果は llvm.llrint 組み込み関数と同じになります。

llvm.experimental.constrained.nearbyint’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.nearbyint(<type> <op1>,
                                         metadata <rounding mode>,
                                         metadata <exception behavior>)
概要:

llvm.experimental.constrained.nearbyint’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。引数が整数でない場合でも、不正確な浮動小数点例外は発生しません。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目と 3 番目の引数は、上記の丸めモードと例外動作を指定します。

セマンティクス:

この関数は、libm の nearbyint 関数と同じ値を返し、エラー条件も同様に処理します。丸めモードは、丸めモード引数によって記述されますが、決定されるわけではありません。実際の丸めモードは、実行時の浮動小数点環境によって決定されます。丸めモード引数は、コンパイラーへの情報提供のみを目的としています。

llvm.experimental.constrained.maxnum’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.maxnum(<type> <op1>, <type> <op2>
                                      metadata <exception behavior>)
概要:

llvm.experimental.constrained.maxnum’ 組み込み関数は、2 つの引数のうち大きい方の値を返します。

引数:

最初の 2 つの引数と戻り値は、同じ型の浮動小数点数です。

3 番目の引数は、上記で説明した例外の動作を指定します。

セマンティクス:

この関数は、maxNum の IEEE-754 セマンティクスに従います。

llvm.experimental.constrained.minnum’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.minnum(<type> <op1>, <type> <op2>
                                      metadata <exception behavior>)
概要:

llvm.experimental.constrained.minnum’ 組み込み関数は、2 つの引数のうち小さい方の値を返します。

引数:

最初の 2 つの引数と戻り値は、同じ型の浮動小数点数です。

3 番目の引数は、上記で説明した例外の動作を指定します。

セマンティクス:

この関数は、minNum の IEEE-754 セマンティクスに従います。

llvm.experimental.constrained.maximum’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.maximum(<type> <op1>, <type> <op2>
                                       metadata <exception behavior>)
概要:

llvm.experimental.constrained.maximum’ 組み込み関数は、2 つの引数のうち大きい方の値を返し、NaN を伝播し、-0.0 を +0.0 より小さいものとして扱います。

引数:

最初の 2 つの引数と戻り値は、同じ型の浮動小数点数です。

3 番目の引数は、上記で説明した例外の動作を指定します。

セマンティクス:

この関数は、IEEE 754-2019 のドラフトで規定されたセマンティクスに従います。

llvm.experimental.constrained.minimum’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.minimum(<type> <op1>, <type> <op2>
                                       metadata <exception behavior>)
概要:

llvm.experimental.constrained.minimum’ 組み込み関数は、2 つの引数のうち小さい方の値を返し、NaN を伝播し、-0.0 を +0.0 より小さいものとして扱います。

引数:

最初の 2 つの引数と戻り値は、同じ型の浮動小数点数です。

3 番目の引数は、上記で説明した例外の動作を指定します。

セマンティクス:

この関数は、IEEE 754-2019 のドラフトで規定されたセマンティクスに従います。

llvm.experimental.constrained.ceil’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.ceil(<type> <op1>,
                                    metadata <exception behavior>)
概要:

llvm.experimental.constrained.ceil’ 組み込み関数は、最初の引数の天井値を返します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の ceil 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.constrained.floor’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.floor(<type> <op1>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.floor’ 組み込み関数は、最初の引数の床関数値を返します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の floor 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.constrained.round’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.round(<type> <op1>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.round’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の round 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.constrained.roundeven’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.roundeven(<type> <op1>,
                                         metadata <exception behavior>)
概要:

llvm.experimental.constrained.roundeven’ 組み込み関数は、最初の引数を浮動小数点形式で最も近い整数に丸めた値を返します。中間値の場合は、現在の丸め方向に依存せず、偶数(つまり、最も近い偶数整数)に丸めます。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、IEEE-754 の演算 roundToIntegralTiesToEven を実装しています。また、C 標準関数の roundeven と同じように動作し、SNAN 引数に対して無効な演算例外を通知する場合があります。

llvm.experimental.constrained.lround’ 組み込み関数

構文:
declare <inttype>
@llvm.experimental.constrained.lround(<fptype> <op1>,
                                      metadata <exception behavior>)
概要:

llvm.experimental.constrained.lround’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。中間値の場合はゼロから離れる方向に丸めます。引数が整数でない場合は、不正確な浮動小数点例外が発生します。結果がサポートされている整数型に収まらないほど大きい場合は、無効な例外が発生し、この場合の結果は未定義です。

引数:

最初の引数は浮動小数点数です。戻り値は整数型です。すべてのターゲットですべての型がサポートされているわけではありません。サポートされている型は、llvm.lround 組み込み関数および lround libm 関数と同じです。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の lround 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.constrained.llround’ 組み込み関数

構文:
declare <inttype>
@llvm.experimental.constrained.llround(<fptype> <op1>,
                                       metadata <exception behavior>)
概要:

llvm.experimental.constrained.llround’ 組み込み関数は、最初の引数を最も近い整数に丸めた値を返します。中間値の場合はゼロから離れる方向に丸めます。引数が整数でない場合は、不正確な浮動小数点例外が発生します。結果がサポートされている整数型に収まらないほど大きい場合は、無効な例外が発生し、この場合の結果は未定義です。

引数:

最初の引数は浮動小数点数です。戻り値は整数型です。すべてのターゲットですべての型がサポートされているわけではありません。サポートされている型は、llvm.llround 組み込み関数および llround libm 関数と同じです。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の llround 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.constrained.trunc’ 組み込み関数

構文:
declare <type>
@llvm.experimental.constrained.trunc(<type> <op1>,
                                     metadata <exception behavior>)
概要:

llvm.experimental.constrained.trunc’ 組み込み関数は、最初の引数を、その引数の絶対値を超えない最も近い整数に丸めた値を返します。

引数:

最初の引数と戻り値は、同じ型の浮動小数点数です。

2 番目の引数は、上記の例外動作を指定します。

セマンティクス:

この関数は、libm の trunc 関数と同じ値を返し、エラー条件も同様に処理します。

llvm.experimental.noalias.scope.decl’ 組み込み関数

構文:
declare void @llvm.experimental.noalias.scope.decl(metadata !id.scope.list)
概要:

llvm.experimental.noalias.scope.decl 組み込み関数は、noalias スコープが宣言されている場所を特定します。組み込み関数が複製される場合、スコープについても決定する必要があります。複製理由に応じて、スコープも複製する必要がある場合があります。

引数:

!id.scope.list 引数は、noalias メタデータ参照のリストであるメタデータです。形式は、noalias メタデータに必要な形式と同一です。このリストには、要素が 1 つだけ含まれている必要があります。

セマンティクス:

llvm.experimental.noalias.scope.decl 組み込み関数は、noalias スコープが宣言されている場所を特定します。組み込み関数が複製される場合、スコープについても決定する必要があります。複製理由に応じて、スコープも複製する必要がある場合があります。

たとえば、組み込み関数がループ本体内で使用されていて、そのループが展開される場合、関連付けられている noalias スコープも複製する必要があります。そうしないと、それが示す noalias プロパティがループの反復をまたいでしまい、単一の反復内でのみ有効になります。

; This examples shows two possible positions for noalias.decl and how they impact the semantics:
; If it is outside the loop (Version 1), then %a and %b are noalias across *all* iterations.
; If it is inside the loop (Version 2), then %a and %b are noalias only within *one* iteration.
declare void @decl_in_loop(ptr %a.base, ptr %b.base) {
entry:
  ; call void @llvm.experimental.noalias.scope.decl(metadata !2) ; Version 1: noalias decl outside loop
  br label %loop

loop:
  %a = phi ptr [ %a.base, %entry ], [ %a.inc, %loop ]
  %b = phi ptr [ %b.base, %entry ], [ %b.inc, %loop ]
  ; call void @llvm.experimental.noalias.scope.decl(metadata !2) ; Version 2: noalias decl inside loop
  %val = load i8, ptr %a, !alias.scope !2
  store i8 %val, ptr %b, !noalias !2
  %a.inc = getelementptr inbounds i8, ptr %a, i64 1
  %b.inc = getelementptr inbounds i8, ptr %b, i64 1
  %cond = call i1 @cond()
  br i1 %cond, label %loop, label %exit

exit:
  ret void
}

!0 = !{!0} ; domain
!1 = !{!1, !0} ; scope
!2 = !{!1} ; scope list

同じスコープに対して @llvm.experimental.noalias.scope.decl を複数回呼び出すことは可能ですが、別の呼び出しを支配することは絶対にあってはなりません。違反は、変換パスまたは入力のいずれかの問題を示すため、検証ツールによって指摘されます。

浮動小数点環境操作組み込み関数

これらの関数は、丸めモードや浮動小数点例外の状態など、浮動小数点環境を読み書きします。浮動小数点環境の変更には特別な注意が必要です。浮動小数点環境を参照してください。

llvm.get.rounding’ 組み込み関数

構文:
declare i32 @llvm.get.rounding()
概要:

llvm.get.rounding’ 組み込み関数は、現在の丸めモードを読み取ります。

セマンティクス:

llvm.get.rounding’ 組み込み関数は、現在の丸めモードを返します。返される値のエンコードは、C 標準で指定されている FLT_ROUNDS の結果と同じです。

0  - toward zero
1  - to nearest, ties to even
2  - toward positive infinity
3  - toward negative infinity
4  - to nearest, ties away from zero

ターゲットでサポートされている追加の丸めモードを表すために、他の値を使用できます。これらの値はターゲット固有です。

llvm.set.rounding’ 組み込み関数

構文:
declare void @llvm.set.rounding(i32 <val>)
概要:

llvm.set.rounding’ 組み込み関数は、現在の丸めモードを設定します。

引数:

引数は、必要な丸めモードです。丸めモードのエンコードは、‘llvm.get.rounding’ で使用されるものと同じです。

セマンティクス:

llvm.set.rounding’ 組み込み関数は、現在の丸めモードを設定します。これは C ライブラリ関数の ‘fesetround’ に似ていますが、この組み込み関数は値を返さず、IEEE 丸めモードのプラットフォームに依存しない表現を使用します。

llvm.get.fpenv’ 組み込み関数

構文:
declare <integer_type> @llvm.get.fpenv()
概要:

llvm.get.fpenv’ 組み込み関数は、現在の浮動小数点環境のビットを返します。戻り値の型はプラットフォーム固有です。

セマンティクス:

llvm.get.fpenv’ 組み込み関数は、現在の浮動小数点環境を読み取り、それを整数値として返します。

llvm.set.fpenv’ 組み込み関数

構文:
declare void @llvm.set.fpenv(<integer_type> <val>)
概要:

llvm.set.fpenv’ 組み込み関数は、現在の浮動小数点環境を設定します。

引数:

引数は、新しい浮動小数点環境を表す整数です。整数型はプラットフォーム固有です。

セマンティクス:

llvm.set.fpenv’ 組み込み関数は、現在の浮動小数点環境を、引数で指定された状態に設定します。この状態は、‘llvm.get.fpenv’ の呼び出しによって以前に取得されたか、プラットフォームに依存する方法で合成されたものである可能性があります。

llvm.reset.fpenv’ 組み込み関数

構文:
declare void @llvm.reset.fpenv()
概要:

llvm.reset.fpenv’ 組み込み関数は、デフォルトの浮動小数点環境を設定します。

セマンティクス:

llvm.reset.fpenv’ 組み込み関数は、現在の浮動小数点環境をデフォルトの状態に設定します。これは ‘fesetenv(FE_DFL_ENV)’ の呼び出しに似ていますが、値を返さない点が異なります。

llvm.get.fpmode’ 組み込み関数

構文:

llvm.get.fpmode’ 組み込み関数は、現在の浮動小数点制御モードのビットを返します。戻り値の型はプラットフォームに依存します。

declare <integer_type> @llvm.get.fpmode()
概要:

llvm.get.fpmode’ 組み込み関数は、現在の動的な浮動小数点制御モードを読み取り、整数値として返します。

引数:

なし。

意味:

llvm.get.fpmode’ 組み込み関数は、丸め方向、精度、非正規数の扱いなど、現在の動的な浮動小数点制御モードを読み取ります。これは C ライブラリ関数の ‘fegetmode’ と似ていますが、この関数は制御モードのセットをメモリに格納するのではなく、整数値として返します。この値のビットの解釈はターゲットに依存します。

llvm.set.fpmode’ 組み込み関数

構文:

llvm.set.fpmode’ 組み込み関数は、現在の浮動小数点制御モードを設定します。

declare void @llvm.set.fpmode(<integer_type> <val>)
概要:

llvm.set.fpmode’ 組み込み関数は、現在の動的な浮動小数点制御モードを設定します。

引数:

引数は、ターゲット依存の方法で整数値として表される浮動小数点制御モードのセットです。

意味:

llvm.set.fpmode’ 組み込み関数は、現在の動的な浮動小数点制御モードを、‘llvm.get.fpmode’ の呼び出しによって取得されたか、ターゲット固有の方法で構築された引数で指定された状態に設定します。これは C ライブラリ関数の ‘fesetmode’ と似ていますが、この関数はメモリから制御モードのセットを読み取るのではなく、整数値として取得します。

llvm.reset.fpmode’ 組み込み関数

構文:
declare void @llvm.reset.fpmode()
概要:

llvm.reset.fpmode’ 組み込み関数は、デフォルトの動的な浮動小数点制御モードを設定します。

引数:

なし。

意味:

llvm.reset.fpmode’ 組み込み関数は、現在の動的な浮動小数点環境をデフォルト状態に設定します。これは C ライブラリ関数呼び出し ‘fesetmode(FE_DFL_MODE)’ と似ていますが、この関数は値を返しません。

浮動小数点テスト組み込み関数

これらの関数は、浮動小数点値のプロパティを取得します。

llvm.is.fpclass’ 組み込み関数

構文:
declare i1 @llvm.is.fpclass(<fptype> <op>, i32 <test>)
declare <N x i1> @llvm.is.fpclass(<vector-fptype> <op>, i32 <test>)
概要:

llvm.is.fpclass’ 組み込み関数は、最初の引数が2番目の引数で指定されたテストを満たすかどうかに応じて、ブール値またはブール値のベクトルを返します。

最初の引数が浮動小数点スカラーの場合、結果の型はブール値(i1)です。

最初の引数が浮動小数点ベクトルの場合、結果の型は最初の引数と同じ数の要素を持つブール値のベクトルです。

引数:

llvm.is.fpclass’ 組み込み関数の最初の引数は、浮動小数点または浮動小数点値のベクトルである必要があります。

2番目の引数は、実行するテストを指定します。これはコンパイル時の整数定数である必要があり、その各ビットは浮動小数点クラスを指定します。

ビット#

浮動小数点クラス

0

シグナリング NaN

1

クワイエット NaN

2

負の無限大

3

負の正規数

4

負の非正規数

5

負のゼロ

6

正のゼロ

7

正の非正規数

8

正の正規数

9

正の無限大

意味:

この関数は、optest で指定された浮動小数点クラスのいずれかに属しているかどうかを確認します。op がベクトルの場合、チェックは要素ごとに行われます。各チェックは、要素の値が指定されたテストを満たす場合に true である i1 の結果を生成します。引数 test は、テストする浮動小数点クラスを各ビットが指定するビットマスクです。たとえば、値 0x108 は正規値のテストを行います。これは、3 ビットと 8 ビットが設定されており、op が正または負の正規値の場合に関数が true を返すことを意味します。この関数は浮動小数点例外を発生させません。この関数は入力値を正規化せず、浮動小数点環境に依存しません。浮動小数点環境に非正規入力値のゼロ化処理("denormal-fp-math" 属性で示されるような)がある場合、非正規値が観察されます(暗黙的にゼロとして扱われることはありません)。

一般的な組み込み関数

このクラスの組み込み関数は、汎用的に設計されており、特定の目的はありません。

llvm.var.annotation’ 組み込み関数

構文:
declare void @llvm.var.annotation(ptr <val>, ptr <str>, ptr <str>, i32  <int>)
概要:

llvm.var.annotation’ 組み込み関数。

引数:

最初の引数は値へのポインタ、2番目の引数はグローバル文字列へのポインタ、3番目の引数はソースファイル名であるグローバル文字列へのポインタ、そして最後の引数は行番号です。

意味:

この組み込み関数は、任意の文字列でローカル変数を注釈付けできるようにします。これは、これらの注釈を探したい特別な目的の最適化に役立ちます。これらには他の定義された用途はありません。これらはコード生成と最適化によって無視されます。

llvm.ptr.annotation.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の幅の整数へのポインタに対して ‘llvm.ptr.annotation’ を使用できます。:ポインタのアドレス空間を指定する必要があります。デフォルトのアドレス空間の識別子は整数 ‘0’ です。

declare ptr @llvm.ptr.annotation.p0(ptr <val>, ptr <str>, ptr <str>, i32 <int>)
declare ptr @llvm.ptr.annotation.p1(ptr addrspace(1) <val>, ptr <str>, ptr <str>, i32 <int>)
概要:

llvm.ptr.annotation’ 組み込み関数。

引数:

最初の引数は任意のビット幅の整数値(何らかの式の結果)へのポインタ、2番目の引数はグローバル文字列へのポインタ、3番目の引数はソースファイル名であるグローバル文字列へのポインタ、そして最後の引数は行番号です。最初の引数の値を返します。

意味:

この組み込み関数を使用すると、任意の文字列で整数へのポインタを注釈付けできます。これは、これらの注釈を探したい特別な目的の最適化に役立ちます。これらには他の定義された用途はありません。変換は最善を尽くして注釈を保持しますが、セマンティクスを壊すことなく組み込み関数を最初の引数に置き換えることが許可されており、組み込み関数は命令選択中に完全に削除されます。

llvm.annotation.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅で ‘llvm.annotation’ を使用できます。

declare i8 @llvm.annotation.i8(i8 <val>, ptr <str>, ptr <str>, i32  <int>)
declare i16 @llvm.annotation.i16(i16 <val>, ptr <str>, ptr <str>, i32  <int>)
declare i32 @llvm.annotation.i32(i32 <val>, ptr <str>, ptr <str>, i32  <int>)
declare i64 @llvm.annotation.i64(i64 <val>, ptr <str>, ptr <str>, i32  <int>)
declare i256 @llvm.annotation.i256(i256 <val>, ptr <str>, ptr <str>, i32  <int>)
概要:

llvm.annotation’ 組み込み関数。

引数:

最初の引数は整数値(何らかの式の結果)、2番目の引数はグローバル文字列へのポインタ、3番目の引数はソースファイル名であるグローバル文字列へのポインタ、そして最後の引数は行番号です。最初の引数の値を返します。

意味:

この組み込み関数を使用すると、任意の文字列を使用して任意の式に注釈を付けることができます。これは、これらの注釈を探したい特別な目的の最適化に役立ちます。これらには他の定義された用途はありません。変換は最善を尽くして注釈を保持しますが、セマンティクスを壊すことなく組み込み関数を最初の引数に置き換えることが許可されており、組み込み関数は命令選択中に完全に削除されます。

llvm.codeview.annotation’ 組み込み関数

構文:

このアノテーションは、プログラムのポイントにラベルを発行し、関連するS_ANNOTATIONコードビューレコードを追加の文字列メタデータとともに発行します。これは、MSVCの__annotation組み込み関数を実装するために使用されます。noduplicateとマークされているため、この組み込み関数への呼び出しはインライン化を妨げ、コストが高いとみなすべきです。

declare void @llvm.codeview.annotation(metadata)
引数:

引数は、任意の数のMDStringを含むMDTupleである必要があります。

llvm.trap’ 組み込み関数

構文:
declare void @llvm.trap() cold noreturn nounwind
概要:

llvm.trap’ 組み込み関数。

引数:

なし。

意味:

この組み込み関数は、ターゲット依存のトラップ命令に低レベル化されます。ターゲットにトラップ命令がない場合、この組み込み関数はabort()関数の呼び出しに低レベル化されます。

llvm.debugtrap’ 組み込み関数

構文:
declare void @llvm.debugtrap() nounwind
概要:

llvm.debugtrap’ 組み込み関数。

引数:

なし。

意味:

この組み込み関数は、デバッガーの注意を喚起することを目的とした実行トラップを引き起こすコードに低レベル化されます。

llvm.ubsantrap’ 組み込み関数

構文:
declare void @llvm.ubsantrap(i8 immarg) cold noreturn nounwind
概要:

llvm.ubsantrap’ 組み込み関数。

引数:

検出された失敗の種類を記述する整数。

意味:

この組み込み関数は、実行トラップを引き起こすコードに低レベル化され、可能な場合クラッシュを区別するために、そのトラップのエンコーディングに引数を埋め込みます。

この動作をサポートしていないターゲットでは、@llvm.trapと同等です。

llvm.stackprotector’ 組み込み関数

構文:
declare void @llvm.stackprotector(ptr <guard>, ptr <slot>)
概要:

llvm.stackprotector組み込み関数は、guardを受け取り、slotのスタックに格納します。スタックのスロットは、ローカル変数の前にスタックに配置されるように調整されます。

引数:

llvm.stackprotector組み込み関数は、2つのポインタ引数を必要とします。最初の引数は、スタックガード@__stack_chk_guardからロードされた値です。2番目の変数は、ガードの値を保持するのに十分なスペースを持つallocaです。

意味:

この組み込み関数は、プロローグ/エピローグインサーターに、スタック上のローカル変数の前にAllocaInstスタックスロットの位置を強制させます。これは、スタック上のローカル変数が上書きされた場合、ガードの値が破壊されるようにするためです。関数が終了すると、スタック上のガードはllvm.stackprotectorcheckによって元のガードに対してチェックされます。それらが異なる場合、llvm.stackprotectorcheckは、__stack_chk_fail()関数を呼び出すことによってプログラムを中止させます。

llvm.stackguard’ 組み込み関数

構文:
declare ptr @llvm.stackguard()
概要:

llvm.stackguard組み込み関数は、システムスタックガードの値を返します。

内部使用のみであるため、フロントエンドで生成すべきではありません。この組み込み関数を作成する理由は、FastISelでIR形式のスタックプロテクターをまだサポートしているためです。

引数:

なし。

意味:

一部のプラットフォームでは、この組み込み関数によって返される値は、同じスレッドでのロード間で変更されません。他のプラットフォームでは、同じグローバル変数(例えば@__stack_chk_guard)の値を返します。

現在、一部のプラットフォームには、llvm.stackguard()で処理されないIRレベルのカスタマイズされたスタックガードローディング(例えば、X86 Linux)がありますが、将来的には処理されるはずです。

llvm.objectsize’ 組み込み関数

構文:
declare i32 @llvm.objectsize.i32(ptr <object>, i1 <min>, i1 <nullunknown>, i1 <dynamic>)
declare i64 @llvm.objectsize.i64(ptr <object>, i1 <min>, i1 <nullunknown>, i1 <dynamic>)
概要:

llvm.objectsize組み込み関数は、a) 操作(memcpyなど)がオブジェクトに対応するバッファーをオーバーフローするかどうか、または b) オーバーフローのランタイムチェックが不要かどうかを判断するために、オプティマイザーに情報を提供するように設計されています。このコンテキストでのオブジェクトとは、特定のクラス、構造体、配列、またはその他のオブジェクトの割り当てを意味します。

引数:

llvm.objectsize組み込み関数は、4つの引数を取ります。最初の引数は、objectへのポインタまたはその中へのポインタです。2番目の引数は、オブジェクトサイズが不明な場合に、llvm.objectsizeが0(trueの場合)または-1(falseの場合)を返すかどうかを決定します。3番目の引数は、アドレス空間0のnullがポインタ引数として使用されたときに、llvm.objectsizeがどのように動作するかを制御します。それがfalseの場合、nullが指定された場合、llvm.objectsizeは0バイトが利用可能であると報告します。それ以外の場合、nullがゼロ以外ののアドレス空間にある場合、またはllvm.objectsizeの3番目の引数にtrueが指定された場合、そのサイズは不明であると想定します。llvm.objectsizeの4番目の引数は、値をランタイムで評価する必要があるかどうかを決定します。

2番目、3番目、4番目の引数は、定数のみを受け入れます。

意味:

llvm.objectsize組み込み関数は、関係するオブジェクトのサイズを表す値に低レベル化されます。サイズを決定できない場合、llvm.objectsizei32/i64 -1 または 0min引数によって異なります)を返します。

llvm.expect’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅でllvm.expectを使用できます。

declare i1 @llvm.expect.i1(i1 <val>, i1 <expected_val>)
declare i32 @llvm.expect.i32(i32 <val>, i32 <expected_val>)
declare i64 @llvm.expect.i64(i64 <val>, i64 <expected_val>)
概要:

llvm.expect組み込み関数は、オプティマイザーで使用できるvalの予想される(最も可能性の高い)値に関する情報を提供します。

引数:

llvm.expect組み込み関数は、2つの引数を取ります。最初の引数は値です。2番目の引数は予想される値です。

意味:

この組み込み関数はvalに低レベル化されます。

llvm.expect.with.probability’ 組み込み関数

構文:

この組み込み関数は、llvm.expectに似ています。これはオーバーロードされた組み込み関数です。任意の整数ビット幅でllvm.expect.with.probabilityを使用できます。

declare i1 @llvm.expect.with.probability.i1(i1 <val>, i1 <expected_val>, double <prob>)
declare i32 @llvm.expect.with.probability.i32(i32 <val>, i32 <expected_val>, double <prob>)
declare i64 @llvm.expect.with.probability.i64(i64 <val>, i64 <expected_val>, double <prob>)
概要:

llvm.expect.with.probability組み込み関数は、オプティマイザーで使用できる、確率(または信頼度)probを持つvalの期待値に関する情報を提供します。

引数:

組み込み関数llvm.expect.with.probabilityは3つの引数を取ります。最初の引数は値です。2番目の引数は期待される値です。3番目の引数は確率です。

意味:

この組み込み関数はvalに低レベル化されます。

llvm.assume」組み込み関数

構文:
declare void @llvm.assume(i1 %cond)
概要:

llvm.assumeを使用すると、オプティマイザは提供された条件が真であると仮定できます。この情報は、コードの他の部分を簡略化する際に使用できます。

より複雑な仮定は、assume オペランドバンドルとしてエンコードできます。

引数:

呼び出しの引数は、オプティマイザが常に真であると仮定できる条件です。

意味:

この組み込み関数を使用すると、オプティマイザは制御フローが組み込み関数呼び出しに到達するたびに、提供された条件が常に真であると仮定できます。この組み込み関数に対してコードは生成されず、提供された条件にのみ寄与する命令はコード生成に使用されません。実行中に条件が破られた場合、動作は未定義です。

オプティマイザは、llvm.assume組み込み関数で使用される値に対して実行される変換を、組み込み関数の入力引数を形成するためにのみ使用される命令を保持するために制限する場合があることに注意してください。 llvm.assume組み込み関数によって提供される追加情報がコード品質の全体的な改善に十分な影響を与えない場合、これは望ましくない可能性があります。このため、llvm.assumeは、オプティマイザが推測できる基本的な数学的不変量や、オプティマイザにとってほとんど役に立たない事実を文書化するために使用しないでください。

llvm.ssa.copy」組み込み関数

構文:
declare type @llvm.ssa.copy(type returned %operand) memory(none)
引数:

最初の引数は、返される値として使用されるオペランドです。

概要:

llvm.ssa.copy組み込み関数は、操作をコピーして新しい名前を付けることで、操作に情報を添付するために使用できます。たとえば、PredicateInfoユーティリティは、拡張SSA形式を構築し、特定の用途を支配するオペランドにさまざまな形式の情報を添付するために使用します。これは、一般的な用途ではなく、特定のポイントで値分割を必要とする一時的な名前変更フォームを構築する場合にのみ使用されます。

llvm.type.test」組み込み関数

構文:
declare i1 @llvm.type.test(ptr %ptr, metadata %type) nounwind memory(none)
引数:

最初の引数は、テストするポインタです。2番目の引数は、型識別子を表すメタデータオブジェクトです。

概要:

llvm.type.test組み込み関数は、指定されたポインタが指定された型識別子に関連付けられているかどうかをテストします。

llvm.type.checked.load」組み込み関数

構文:
declare {ptr, i1} @llvm.type.checked.load(ptr %ptr, i32 %offset, metadata %type) nounwind memory(argmem: read)
引数:

最初の引数は、関数ポインタをロードするポインタです。2番目の引数は、関数ポインタをロードするバイトオフセットです。3番目の引数は、型識別子を表すメタデータオブジェクトです。

概要:

llvm.type.checked.load組み込み関数は、型メタデータを使用して、仮想テーブルポインタから関数ポインタを安全にロードします。この組み込み関数は、仮想呼び出しの最適化と組み合わせて、制御フローの整合性を実装するために使用されます。仮想呼び出しの最適化パスでは、非仮想化された呼び出しに関連付けられたllvm.type.checked.load組み込み関数を最適化して削除し、制御フローの整合性の制約を強制する必要がない場合は型チェックを削除します。

指定されたポインタが型メタデータ識別子に関連付けられている場合、この関数は、その戻り値の2番目の要素としてtrueを返します。(この関数は、指定されたポインタが型メタデータ識別子に関連付けられていない場合でもtrueを返す可能性があることに注意してください。)関数の戻り値の2番目の要素がtrueの場合、最初の要素には次の規則が適用されます。

  • 指定されたポインタが指定された型メタデータ識別子に関連付けられている場合、指定されたポインタからの指定されたバイトオフセットからロードされた関数ポインタです。

  • 指定されたポインタが指定された型メタデータ識別子に関連付けられていない場合、次のいずれかになります(選択は指定されていません)。

    1. 型メタデータに関連付けられた、任意に選択された(指定されていないメカニズムを介して)ポインタからロードされたであろう関数ポインタ。

    2. 関数にvoid以外の戻り値の型がある場合、副作用を引き起こさずに不特定の値を返す関数のポインタ。

関数の戻り値の2番目の要素がfalseの場合、最初の要素の値は未定義です。

llvm.type.checked.load.relative」組み込み関数

構文:
declare {ptr, i1} @llvm.type.checked.load.relative(ptr %ptr, i32 %offset, metadata %type) nounwind memory(argmem: read)
概要:

llvm.type.checked.load.relative組み込み関数は、メタデータを使用して、仮想テーブルポインタから関数への相対ポインタをロードします。それ以外の場合、そのセマンティクスはllvm.type.checked.load組み込み関数と同じです。

相対ポインタは、ポインタが指す値へのオフセットを指すポインタです。相対ポインタの基になるポインタのアドレスは、オフセットのアドレスにオフセットを加算することで取得されます。

llvm.arithmetic.fence」組み込み関数

構文:
declare <type>
@llvm.arithmetic.fence(<type> <op>)
概要:

llvm.arithmetic.fence組み込み関数の目的は、オプティマイザが引数と引数を含む式の間のfast-math最適化(特に再結合)を実行するのを防ぐことです。これは、ソース言語の括弧を保持するために使用できます。

引数:

llvm.arithmetic.fence組み込み関数は、1つの引数のみを取ります。引数と戻り値は、同じ型の浮動小数点数または浮動小数点数のベクトルです。

意味:

この組み込み関数は、そのオペランドの値を返します。オプティマイザは引数を最適化できますが、オプティマイザはオペランドのコンポーネントを包含コンテキストに昇格させることはできず、オプティマイザは包含コンテキスト内の式の計算をオペランドに移動させることはできません。

llvm.donothing」組み込み関数

構文:
declare void @llvm.donothing() nounwind memory(none)
概要:

llvm.donothing組み込み関数は、操作を実行しません。これは、(llvm.experimental.patchpointおよびllvm.experimental.gc.statepointに加えて)invoke命令で呼び出すことができる3つの組み込み関数のうちの1つです。

引数:

なし。

意味:

この組み込み関数は何もせず、オプティマイザによって削除され、コード生成によって無視されます。

llvm.experimental.deoptimize」組み込み関数

構文:
declare type @llvm.experimental.deoptimize(...) [ "deopt"(...) ]
概要:

この組み込み関数は、最適化解除オペランドバンドルとともに、フロントエンドが現在実行中の(通常はより専門化されているため高速な)バージョンの関数から別の(通常はより汎用的であるため低速な)バージョンへの制御の転送とフレームローカルの状態を表すことを可能にします。

JavaやJavaScriptのような完全に統合されたマネージドランタイムを持つ言語では、この組み込み関数を使用して、「uncommon trap」や「side exit」のような機能を実装できます。CやC++のような非マネージド言語では、この組み込み関数を使用して、特殊化された関数の低速パスを表現できます。

引数:

この組み込み関数は任意の数の引数を取ります。その意味は、低減戦略によって決定されます。

意味:

@llvm.experimental.deoptimize組み込み関数は、添付された最適化解除継続(最適化解除オペランドバンドルを使用して示される)を実行し、最適化解除継続によって返される値を返します。継続自体のセマンティックプロパティの定義は、言語リファレンスの範囲外です。LLVMに関する限り、最適化解除継続は、ヒープ全体からの読み取りやヒープ全体への書き込みなど、任意の副作用を呼び出すことができます。

"deopt"オペランドバンドルを使用して表現された最適化解除継続は、常にそれらを含む物理フレームの最後まで実行を継続するため、@llvm.experimental.deoptimizeへのすべての呼び出しは「テール位置」にある必要があります。

  • @llvm.experimental.deoptimizeを呼び出すことはできません。

  • 呼び出しは、ret命令の直前にある必要があります。

declare void @llvm.experimental.guard(i1, ...) [ "deopt"(...) ]

define void @llvm.experimental.guard(i1 %pred, <args...>) {
  %realPred = and i1 %pred, undef
  br i1 %realPred, label %continue, label %leave [, !make.implicit !{}]

leave:
  call void @llvm.experimental.deoptimize(<args...>) [ "deopt"() ]
  ret void

continue:
  ret void
}

declare i1 @llvm.experimental.widenable.condition()

なし。

  %cond = call i1 @llvm.experimental.widenable.condition()
  br i1 %cond, label %fast_path, label %slow_path

fast_path:
  ; Apply memory-consuming but fast solution for a task.

slow_path:
  ; Cheap in memory but slow solution.

block:
  ; Unguarded instructions
  call void @llvm.experimental.guard(i1 %cond, <args...>) ["deopt"(<deopt_args...>)]
  ; Guarded instructions

block:
  ; Unguarded instructions
  %widenable_condition = call i1 @llvm.experimental.widenable.condition()
  %guard_condition = and i1 %cond, %widenable_condition
  br i1 %guard_condition, label %guarded, label %deopt

guarded:
  ; Guarded instructions

deopt:
  call type @llvm.experimental.deoptimize(<args...>) [ "deopt"(<deopt_args...>) ]

%widenable_cond = call i1 @llvm.experimental.widenable.condition()
%guard_cond = and i1 %cond, %widenable_cond
br i1 %guard_cond, label %guarded, label %deopt

%widenable_cond = call i1 @llvm.experimental.widenable.condition()
%new_cond = and i1 %any_other_cond, %widenable_cond
%new_guard_cond = and i1 %cond, %new_cond
br i1 %new_guard_cond, label %guarded, label %deopt

declare i1 @llvm.allow.ubsan.check(i8 immarg %kind)

  %allow = call i1 @llvm.allow.ubsan.check(i8 5)
  %not.allow = xor i1 %allow, true
  %cond = or i1 %ubcheck, %not.allow
  br i1 %cond, label %cont, label %trap

cont:
  ; Proceed

trap:
  call void @llvm.ubsantrap(i8 5)
  unreachable

declare i1 @llvm.allow.runtime.check(metadata %kind)

  %allow = call i1 @llvm.allow.runtime.check(metadata !"my_check")
  br i1 %allow, label %fast_path, label %slow_path

fast_path:
  ; Omit diagnostics.

slow_path:
  ; Additional diagnostics.

declare ptr @llvm.load.relative.iN(ptr %ptr, iN %offset) nounwind memory(argmem: read)

この組み込み関数は、アドレス %ptr + %offset から 32 ビット値をロードし、その値に %ptr を加えて返します。定数フォルダーは、この組み込み関数の形式と、それがロードする可能性のある定数初期化子を特別に認識します。ロードされた定数初期化子が i32 trunc(x - %ptr) の形式であることがわかっている場合、組み込み関数の呼び出しは x にフォールドされます。

LLVM は、xunnamed_addr 関数である場合、ミディアムコードモデルでは、このような定数初期化子の計算はリンク時にオーバーフローしないことを保証します。ただし、関数本体にフォールドされた定数初期化子については、この保証は提供しません。この組み込み関数は、このような定数からロードする際のオーバーフローの可能性を回避するために使用できます。

llvm.sideeffect’ 組み込み関数

構文:
declare void @llvm.sideeffect() inaccessiblememonly nounwind willreturn
概要:

llvm.sideeffect 組み込み関数は、何の操作も実行しません。オプティマイザはこれを副作用を持つものとして扱うため、ループが終了しないと仮定すべきではないことを示すためにループに挿入できます (これにより、他の副作用がない無限ループであっても、ループ全体が最適化されて削除される可能性があります)。

引数:

なし。

セマンティクス:

この組み込み関数は実際には何も行いませんが、オプティマイザは外部から観測可能な副作用があると仮定する必要があります。

llvm.is.constant.*’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の引数型で llvm.is.constant を使用できます。

declare i1 @llvm.is.constant.i32(i32 %operand) nounwind memory(none)
declare i1 @llvm.is.constant.f32(float %operand) nounwind memory(none)
declare i1 @llvm.is.constant.TYPENAME(TYPE %operand) nounwind memory(none)
概要:

llvm.is.constant’ 組み込み関数は、引数が明示的なコンパイル時定数であることがわかっている場合に true を返します。これは、マシンコードを生成する前に true または false のいずれかにフォールドされることが保証されています。

セマンティクス:

この組み込み関数はコードを生成しません。引数が明示的なコンパイル時定数値であることがわかっている場合、組み込み関数は定数の true 値に変換されます。それ以外の場合は、定数の false 値に変換されます。

特に、引数がグローバルを参照する定数式である場合 (そのアドレスは定数ですが、コンパイル時には明示的ではありません)、組み込み関数は false に評価されることに注意してください。

結果は、最適化パスの結果にも意図的に依存します。たとえば、関数がインライン化されるかどうかによって結果が変更される可能性があります。関数のパラメーターは明らかに定数ではありません。ただし、llvm.is.constant.i32(i32 %param) のような呼び出しは、関数がインライン化された後、関数のパラメーターに渡された値が定数であった場合に、true を返す可能性があります。

llvm.ptrmask’ 組み込み関数

構文:
declare ptrty llvm.ptrmask(ptrty %ptr, intty %mask) speculatable memory(none)
引数:

最初の引数は、ポインターまたはポインターのベクターです。2 番目の引数は、最初の引数のインデックス型サイズと同じビット幅を持つ整数または整数のベクターです。

概要:

llvm.ptrmask 組み込み関数は、マスクに従ってポインターのビットをマスクします。これにより、ポインターを整数に変換 (ptrtoint/inttoptr) しなくても、タグ付きポインターからデータを削除できます。その結果、エイリアス解析と基礎オブジェクトの検出を容易にするために、より多くの情報を保持できます。

セマンティクス:

ptrmask(%ptr, %mask) の結果は、次の展開と同等です。ここで、iPtrIdx はポインターのインデックス型サイズです。

%intptr = ptrtoint ptr %ptr to iPtrIdx ; this may truncate
%masked = and iPtrIdx %intptr, %mask
%diff = sub iPtrIdx %masked, %intptr
%result = getelementptr i8, ptr %ptr, iPtrIdx %diff

ポインターのインデックス型サイズがポインター型サイズよりも小さい場合、これは、インデックスサイズを超えるポインタービットがこの組み込み関数によって影響を受けないことを意味します。整数ポインターの場合、マスクがポインター型サイズまで 1 ビットで拡張されたかのように動作します。

返されたポインターと最初の引数の両方が、同じ基礎オブジェクトに基づいています (基づいているという用語の詳細については、ポインターエイリアスの規則を参照してください)。

組み込み関数は、戻り値を介してのみポインター引数をキャプチャします。

llvm.threadlocal.address’ 組み込み関数

構文:
declare ptr @llvm.threadlocal.address(ptr) nounwind willreturn memory(none)
引数:

llvm.threadlocal.address 組み込み関数には、スレッドローカルであるグローバル値引数 (グローバル変数またはエイリアス) が必要です。

セマンティクス:

スレッドローカルグローバルのアドレスは、呼び出しスレッドに依存するため、定数ではありません。llvm.threadlocal.address 組み込み関数は、呼び出しスレッド内の指定されたスレッドローカルグローバルのアドレスを返します。

llvm.vscale’ 組み込み関数

構文:
declare i32 llvm.vscale.i32()
declare i64 llvm.vscale.i64()
概要:

llvm.vscale 組み込み関数は、<vscale x 16 x i8> のようなスケーラブルベクターの vscale の値を返します。

セマンティクス:

vscale は、プログラムの実行を通じて一定ですが、コンパイル時には不明な正の値です。結果値が結果型に収まらない場合、結果はポイズン値です。

llvm.fake.use’ 組み込み関数

構文:
declare void @llvm.fake.use(...)
概要:

llvm.fake.use 組み込み関数は、no-op です。単一の値をオペランドとして受け取り、そのオペランドの使用として扱われ、オプティマイザにフェイクユースの前にその値を保持させます。これは、変数の有効期間を延長するために使用されます。変数のスコープの最後に配置されたこの組み込み関数は、その変数が最適化されて削除されるのを防ぐのに役立ちます。

引数:

llvm.fake.use 組み込み関数は、任意の関数ローカル SSA 値である可能性のある 1 つの引数を取ります。シグネチャは可変長であるため、組み込み関数は任意の型の引数を受け入れることができますが、複数の引数を渡すとエラーが発生することに注意してください。

セマンティクス:

この組み込み関数は何も行いませんが、オプティマイザはそれを単一のオペランドの使用と見なし、組み込み関数とその関数内の位置を保持しようとする必要があります。

スタックマップ組み込み関数

LLVM は、動的言語 JIT で一般的に必要とされるランタイムパッチメカニズムをサポートするための実験的な組み込み関数を提供します。これらの組み込み関数については、LLVM のスタックマップとパッチポイントで説明しています。

要素ごとのアトミックメモリー組み込み関数

これらの組み込み関数は、標準ライブラリのメモリー組み込み関数に似ていますが、メモリー転送をアトミックメモリーアクセスのシーケンスとして実行するという点が異なります。

llvm.memcpy.element.unordered.atomic’ 組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅および異なるアドレス空間で llvm.memcpy.element.unordered.atomic を使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i32(ptr <dest>,
                                                             ptr <src>,
                                                             i32 <len>,
                                                             i32 <element_size>)
declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr <dest>,
                                                             ptr <src>,
                                                             i64 <len>,
                                                             i32 <element_size>)
概要:

llvm.memcpy.element.unordered.atomic.*’ 組み込み関数は、‘llvm.memcpy.*’ 組み込み関数の特殊化です。これは、dest および src が正確に element_size バイトの要素を持つ配列として扱われ、バッファー間のコピーが 順序付けられていないアトミック なロード/ストア操作のシーケンスを使用するという点で異なり、そのサイズは element_size の正の整数倍です。

引数:

最初の 3 つの引数は、@llvm.memcpy 組み込み関数の場合と同じですが、lenelement_size の正の整数倍である必要があるという制約が追加されています。lenelement_size の正の整数倍でない場合、組み込み関数の動作は未定義です。

element_size は、ターゲット固有のアトミックアクセスサイズ制限を超えない、コンパイル時定数の正の 2 の累乗である必要があります。

各入力ポインタについて、align パラメータ属性を指定する必要があります。これは、element_size 以上の2のべき乗でなければなりません。呼び出し元は、ソースとデスティネーションの両方のポインタがその境界にアラインされていることを保証します。

セマンティクス:

llvm.memcpy.element.unordered.atomic.*」組み込み関数は、ソースロケーションからデスティネーションロケーションに len バイトのメモリをコピーします。これらのロケーションは重複できません。メモリコピーは、各アクセスが element_size バイト幅の倍数であり、element_size 境界でアラインされていることが保証されている、ロード/ストア操作のシーケンスとして実行されます。

コピーの順序は指定されていません。ソースバッファから同じ値が何度も読み取られる可能性がありますが、デスティネーションバッファには要素ごとに1回だけ書き込みが発行されます。ソースとデスティネーションの両方への同時読み取りと書き込みを行うことは、指定されている場合に、それらの読み取りと書き込みが順不同のアトミックである限り、適切に定義されています。

この組み込み関数は、ソースロケーションからの順不同のロードと、デスティネーションへのストアのセットによって提供される以上の順序付けの保証を提供しません。

低レベル化:

最も一般的なケースでは、「llvm.memcpy.element.unordered.atomic.*」の呼び出しは、シンボル __llvm_memcpy_element_unordered_atomic_* の呼び出しに低レベル化されます。ここで、「*」は実際の要素サイズに置き換えられます。GC固有の低レベル化の詳細については、RewriteStatepointsForGC 組み込み関数の低レベル化 を参照してください。

最適化コンパイラは、メモリコピーが有益な場合にインライン化することを許可されています。

llvm.memmove.element.unordered.atomic」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅および異なるアドレス空間で llvm.memmove.element.unordered.atomic を使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memmove.element.unordered.atomic.p0.p0.i32(ptr <dest>,
                                                              ptr <src>,
                                                              i32 <len>,
                                                              i32 <element_size>)
declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr <dest>,
                                                              ptr <src>,
                                                              i64 <len>,
                                                              i32 <element_size>)
概要:

llvm.memmove.element.unordered.atomic.*」組み込み関数は、「llvm.memmove.*」組み込み関数の特殊化です。これは、destsrc がちょうど element_size バイトの要素を持つ配列として扱われ、バッファ間のコピーが 順不同のアトミック ロード/ストア操作のシーケンスを使用する点で異なります。この操作は、element_size のサイズの正の整数倍数です。

引数:

最初の3つの引数は、@llvm.memmove 組み込み関数と同じですが、lenelement_size の正の整数倍数である必要があるという制約が追加されています。lenelement_size の正の整数倍数でない場合、組み込み関数の動作は未定義です。

element_size は、ターゲット固有のアトミックアクセスサイズ制限以下の、コンパイル時定数の正の2のべき乗である必要があります。

各入力ポインタについて、align パラメータ属性を指定する必要があります。これは、element_size 以上の2のべき乗でなければなりません。呼び出し元は、ソースとデスティネーションの両方のポインタがその境界にアラインされていることを保証します。

セマンティクス:

llvm.memmove.element.unordered.atomic.*」組み込み関数は、ソースロケーションからデスティネーションロケーションに len バイトのメモリをコピーします。これらのロケーションは重複できます。メモリコピーは、各アクセスが element_size バイト幅の倍数であり、element_size 境界でアラインされていることが保証されている、ロード/ストア操作のシーケンスとして実行されます。

コピーの順序は指定されていません。ソースバッファから同じ値が何度も読み取られる可能性がありますが、デスティネーションバッファには要素ごとに1回だけ書き込みが発行されます。ソースとデスティネーションの両方への同時読み取りと書き込みを行うことは、指定されている場合に、それらの読み取りと書き込みが順不同のアトミックである限り、適切に定義されています。

この組み込み関数は、ソースロケーションからの順不同のロードと、デスティネーションへのストアのセットによって提供される以上の順序付けの保証を提供しません。

低レベル化:

最も一般的なケースでは、「llvm.memmove.element.unordered.atomic.*」の呼び出しは、シンボル __llvm_memmove_element_unordered_atomic_* の呼び出しに低レベル化されます。ここで、「*」は実際の要素サイズに置き換えられます。GC固有の低レベル化の詳細については、RewriteStatepointsForGC 組み込み関数の低レベル化 を参照してください。

最適化コンパイラは、メモリコピーが有益な場合にインライン化することを許可されています。

llvm.memset.element.unordered.atomic」組み込み関数

構文:

これはオーバーロードされた組み込み関数です。任意の整数ビット幅および異なるアドレス空間で llvm.memset.element.unordered.atomic を使用できます。ただし、すべてのターゲットがすべてのビット幅をサポートしているわけではありません。

declare void @llvm.memset.element.unordered.atomic.p0.i32(ptr <dest>,
                                                          i8 <value>,
                                                          i32 <len>,
                                                          i32 <element_size>)
declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr <dest>,
                                                          i8 <value>,
                                                          i64 <len>,
                                                          i32 <element_size>)
概要:

llvm.memset.element.unordered.atomic.*」組み込み関数は、「llvm.memset.*」組み込み関数の特殊化です。これは、dest がちょうど element_size バイトの要素を持つ配列として扱われ、その配列への代入が 順不同のアトミック ストア操作のシーケンスを使用する点で異なります。この操作は、element_size のサイズの正の整数倍数です。

引数:

最初の3つの引数は、@llvm.memset 組み込み関数と同じですが、lenelement_size の正の整数倍数である必要があるという制約が追加されています。lenelement_size の正の整数倍数でない場合、組み込み関数の動作は未定義です。

element_size は、ターゲット固有のアトミックアクセスサイズ制限を超えない、コンパイル時定数の正の 2 の累乗である必要があります。

dest 入力ポインタには、align パラメータ属性を指定する必要があります。これは、element_size 以上の2のべき乗でなければなりません。呼び出し元は、デスティネーションポインタがその境界にアラインされていることを保証します。

セマンティクス:

llvm.memset.element.unordered.atomic.*」組み込み関数は、デスティネーションロケーションから始まる len バイトのメモリを、指定された value に設定します。メモリは、各アクセスが element_size バイト幅の倍数であり、element_size 境界でアラインされていることが保証されている、ストア操作のシーケンスで設定されます。

代入の順序は指定されていません。デスティネーションバッファには、要素ごとに1回だけ書き込みが発行されます。指定されている場合に、それらの読み取りと書き込みが順不同のアトミックである限り、デスティネーションへの同時読み取りと書き込みを行うことは適切に定義されています。

この組み込み関数は、デスティネーションへの順不同のストアのセットによって提供される以上の順序付けの保証を提供しません。

低レベル化:

最も一般的なケースでは、「llvm.memset.element.unordered.atomic.*」の呼び出しは、シンボル __llvm_memset_element_unordered_atomic_* の呼び出しに低レベル化されます。ここで、「*」は実際の要素サイズに置き換えられます。

最適化コンパイラは、メモリアサインメントが有益な場合にインライン化することを許可されています。

Objective-C ARC ランタイム組み込み関数

LLVMは、Objective-C ARCランタイムのエントリーポイントに低レベル化される組み込み関数を提供します。LLVMはこれらの関数のセマンティクスを認識しており、その知識に基づいて最適化します。Objective-C ARCの詳細については、こちらを参照してください。

llvm.objc.autorelease」組み込み関数

構文:
declare ptr @llvm.objc.autorelease(ptr)
低レベル化:

objc_autorelease の呼び出しに低レベル化されます。

llvm.objc.autoreleasePoolPop」組み込み関数

構文:
declare void @llvm.objc.autoreleasePoolPop(ptr)
低レベル化:

objc_autoreleasePoolPop の呼び出しに低レベル化されます。

llvm.objc.autoreleasePoolPush」組み込み関数

構文:
declare ptr @llvm.objc.autoreleasePoolPush()
低レベル化:

objc_autoreleasePoolPush の呼び出しに低レベル化します。

llvm.objc.autoreleaseReturnValue’ 組み込み関数

構文:
declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
低レベル化:

objc_autoreleaseReturnValue の呼び出しに低レベル化します。

llvm.objc.copyWeak’ 組み込み関数

構文:
declare void @llvm.objc.copyWeak(ptr, ptr)
低レベル化:

objc_copyWeak の呼び出しに低レベル化します。

llvm.objc.destroyWeak’ 組み込み関数

構文:
declare void @llvm.objc.destroyWeak(ptr)
低レベル化:

objc_destroyWeak の呼び出しに低レベル化します。

llvm.objc.initWeak’ 組み込み関数

構文:
declare ptr @llvm.objc.initWeak(ptr, ptr)
低レベル化:

objc_initWeak の呼び出しに低レベル化します。

llvm.objc.loadWeak’ 組み込み関数

構文:
declare ptr @llvm.objc.loadWeak(ptr)
低レベル化:

objc_loadWeak の呼び出しに低レベル化します。

llvm.objc.loadWeakRetained’ 組み込み関数

構文:
declare ptr @llvm.objc.loadWeakRetained(ptr)
低レベル化:

objc_loadWeakRetained の呼び出しに低レベル化します。

llvm.objc.moveWeak’ 組み込み関数

構文:
declare void @llvm.objc.moveWeak(ptr, ptr)
低レベル化:

objc_moveWeak の呼び出しに低レベル化します。

llvm.objc.release’ 組み込み関数

構文:
declare void @llvm.objc.release(ptr)
低レベル化:

objc_release の呼び出しに低レベル化します。

llvm.objc.retain’ 組み込み関数

構文:
declare ptr @llvm.objc.retain(ptr)
低レベル化:

objc_retain の呼び出しに低レベル化します。

llvm.objc.retainAutorelease’ 組み込み関数

構文:
declare ptr @llvm.objc.retainAutorelease(ptr)
低レベル化:

objc_retainAutorelease の呼び出しに低レベル化します。

llvm.objc.retainAutoreleaseReturnValue’ 組み込み関数

構文:
declare ptr @llvm.objc.retainAutoreleaseReturnValue(ptr)
低レベル化:

objc_retainAutoreleaseReturnValue の呼び出しに低レベル化します。

llvm.objc.retainAutoreleasedReturnValue’ 組み込み関数

構文:
declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
低レベル化:

objc_retainAutoreleasedReturnValue の呼び出しに低レベル化します。

llvm.objc.retainBlock’ 組み込み関数

構文:
declare ptr @llvm.objc.retainBlock(ptr)
低レベル化:

objc_retainBlock の呼び出しに低レベル化します。

llvm.objc.storeStrong’ 組み込み関数

構文:
declare void @llvm.objc.storeStrong(ptr, ptr)
低レベル化:

objc_storeStrong の呼び出しに低レベル化します。

llvm.objc.storeWeak’ 組み込み関数

構文:
declare ptr @llvm.objc.storeWeak(ptr, ptr)
低レベル化:

objc_storeWeak の呼び出しに低レベル化します。

デバッグ情報保持組み込み関数

これらの組み込み関数は、IRレベルの操作とともに特定のデバッグ情報を伝達するために使用されます。たとえば、構造体/共用体の名前と、元のユーザーレベルのフィールドインデックスを知ることが望ましい場合があります。IRタイプがデバッグ情報タイプと異なり、共用体がIRで構造体に変換されるため、このような情報はIR GetElementPtr命令で失われます。

llvm.preserve.array.access.index’ 組み込み関数

構文:
declare <ret_type>
@llvm.preserve.array.access.index.p0s_union.anons.p0a10s_union.anons(<type> base,
                                                                     i32 dim,
                                                                     i32 index)
概要:

llvm.preserve.array.access.index’ 組み込み関数は、配列ベース base、配列次元 dim、および配列への最後のアクセスインデックス index に基づいて getelementptr アドレスを返します。戻り型 ret_type は配列要素へのポインタ型です。配列 dimindex は保持され、コンパイラ変換の影響を受ける可能性のある getelementptr 命令よりも堅牢です。llvm.preserve.access.index タイプのメタデータは、配列またはポインターのデバッグ情報型を提供するために、この呼び出し命令にアタッチされます。メタデータは、type のデバッグ情報バージョンを表す DICompositeType または DIDerivedType です。

引数:

base は配列のベースアドレスです。dim は配列の次元です。dim が 0 の場合、base はポインターです。index は、配列またはポインターへの最後のアクセスインデックスです。

base 引数は、呼び出しサイトで elementtype 属性で注釈を付ける必要があります。この属性は、getelementptr 要素タイプを指定します。

セマンティクス:

llvm.preserve.array.access.index’ 組み込み関数は、ベースが base で、アクセスオペランドが {dim's 0's, index} の getelementptr と同じ結果を生成します。

llvm.preserve.union.access.index’ 組み込み関数

構文:
declare <type>
@llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(<type> base,
                                                                  i32 di_index)
概要:

llvm.preserve.union.access.index’ イントリンシックは、デバッグ情報フィールドのインデックスdi_indexを保持し、baseアドレスを返します。llvm.preserve.access.index型のメタデータは、この呼び出し命令にアタッチされ、共用体デバッグ情報型を提供します。メタデータは、typeのデバッグ情報バージョンを表すDICompositeTypeです。戻り値の型typeは、baseの型と同じです。

引数:

baseは、共用体のベースアドレスです。di_indexは、デバッグ情報におけるフィールドインデックスです。

意味論:

llvm.preserve.union.access.index’ イントリンシックは、baseアドレスを返します。

llvm.preserve.struct.access.index’ イントリンシック

構文:
declare <ret_type>
@llvm.preserve.struct.access.index.p0i8.p0s_struct.anon.0s(<type> base,
                                                           i32 gep_index,
                                                           i32 di_index)
概要:

llvm.preserve.struct.access.index’ イントリンシックは、構造体のベースbaseとIR構造体メンバインデックスgep_indexに基づいてgetelementptrアドレスを返します。llvm.preserve.access.index型のメタデータは、この呼び出し命令にアタッチされ、構造体デバッグ情報型を提供します。メタデータは、typeのデバッグ情報バージョンを表すDICompositeTypeです。戻り値の型ret_typeは、構造体メンバへのポインタ型です。

引数:

baseは、構造体のベースアドレスです。gep_indexは、IR構造体に基づく構造体メンバインデックスです。di_indexは、デバッグ情報に基づく構造体メンバインデックスです。

base 引数は、呼び出しサイトで elementtype 属性で注釈を付ける必要があります。この属性は、getelementptr 要素タイプを指定します。

意味論:

llvm.preserve.struct.access.index’ イントリンシックは、ベースbaseとアクセスオペランド{0, gep_index}を持つgetelementptrと同じ結果を生成します。

llvm.fptrunc.round’ イントリンシック

構文:
declare <ty2>
@llvm.fptrunc.round(<type> <value>, metadata <rounding mode>)
概要:

llvm.fptrunc.round’ イントリンシックは、浮動小数点valueを指定された丸めモードで型ty2に切り詰めます。

引数:

llvm.fptrunc.round’ イントリンシックは、キャストする浮動小数点値と、キャスト先の浮動小数点型を取ります。この引数は、結果よりもサイズが大きくなければなりません。

2番目の引数は、制約付きイントリンシックのセクションで説明されている丸めモードを指定します。このイントリンシックでは、「round.dynamic」モードはサポートされていません。

意味論:

llvm.fptrunc.round’ イントリンシックは、より大きな浮動小数点型のvalueを、より小さな浮動小数点型にキャストします。このイントリンシックは、丸めモードを除いて、デフォルトの浮動小数点環境で実行されると想定されます。このイントリンシックは、すべてのターゲットでサポートされているわけではありません。一部のターゲットでは、すべての丸めモードをサポートしていない場合があります。