已知位元分析¶
已知位元分析遍歷會將有關位元已知值的資訊提供給其他遍歷,以便啟用如下例所示的轉換。這些資訊會延遲計算,因此您只需為使用的部分付出代價。
範例¶
一個簡單的例子是將
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
仍然具有與轉換前相同的已知位元。許多轉換都具有此屬性。主要的例外是當轉換導致未定義的位元被定義為零、一或已定義但未知時。
用法¶
要在遍歷中使用已知位元分析,請先包含標頭並使用 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 參考