已知位分析

已知位分析pass使关于位的已知值的信息可用于其他pass,以实现如下面示例中的转换。信息是延迟计算的,因此您只需为您使用的内容付费。

示例

一个简单的例子是将

a + 1

转换为

a | 1

仅当加法不进位时才有效。换句话说,仅当 a & 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 仍然具有与转换前相同的已知位。许多转换都共享此属性。主要的例外是当转换导致未定义的位变为定义为零、一或已定义但未知时。

用法

要在pass中使用已知位分析,首先包含头文件并使用 INITIALIZE_PASS_DEPENDENCY 注册依赖项。

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

...

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

并在 getAnalysisUsage 中请求pass。

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 参考