既知ビット分析

既知ビット分析パスは、既知のビット値に関する情報を他のパスで利用可能にし、次のような例で見られる変換を有効にします。この情報は必要に応じて遅延して計算されるので、使用したものに対してのみ代金を支払う必要があります。

簡単な例は、次を変換することです。

a + 1

a | 1

に変換します。この変換は加算がキャリーしない場合にのみ有効です。つまり、a & 1 がゼロの場合にのみ有効です。

もう 1 つの例は次のとおりです。

%1:(s32) = G_CONSTANT i32 0xFF0
%2:(s32) = G_AND %0, %1
%3:(s32) = G_CONSTANT i32 0x0FF
%4:(s32) = G_AND %2, %3

定数と G_AND の定義を使用して既知ビットを判定できます。

                                 ; %0 = 0x????????
%1:(s32) = G_CONSTANT i32 0xFF0  ; %1 = 0x00000FF0
%2:(s32) = G_AND %0, %1          ; %2 = 0x00000??0
%3:(s32) = G_CONSTANT i32 0x0FF  ; %3 = 0x000000FF
%4:(s32) = G_AND %2, %3          ; %4 = 0x000000?0

次にこれを使用して式を簡略化します。

                                 ; %0 = 0x????????
%5:(s32) = G_CONSTANT i32 0x0F0  ; %5 = 0x00000FF0
%4:(s32) = G_AND %0, %5          ; %4 = 0x000000?0

%4 は変換後も既知ビットが変換前と同じであることに注意してください。多くの変換がこうしたプロパティを共有しています。主な例外は、変換によって未定義のビットがゼロ、1、または未定義だが既知になった場合です。

使い方

パスで既知ビット分析を使用するには、まずヘッダーを含み、INITIALIZE_PASS_DEPENDENCY で依存関係を登録します。

#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"

...

INITIALIZE_PASS_BEGIN(...)
INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
INITIALIZE_PASS_END(...)

そして getAnalysisUsage でパスを要求します。

void MyPass::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<GISelKnownBitsAnalysis>();
  // Optional: If your pass preserves known bits analysis (many do) then
  //           indicate that it's preserved for re-use by another pass here.
  AU.addPreserved<GISelKnownBitsAnalysis>();
}

次に、分析を取得して使用するだけです。

bool MyPass::runOnMachineFunction(MachineFunction &MF) {
  ...
  GISelKnownBits &KB = getAnalysis<GISelKnownBitsAnalysis>().get(MF);
  ...
  MachineInstr *MI = ...;
  KnownBits Known = KB->getKnownBits(MI->getOperand(0).getReg());
  if (Known.Zeros & 1) {
    // Bit 0 is known to be zero
  }
  ...
}

getKnownBits() 以外にも多数の API があります。詳細については API リファレンス を参照してください