You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在LLVM IR中运行时检查i64值的高位是否为0?

实现i64类型Value高位的运行时检查(LLVM IR插桩方案)

核心思路:利用llvm.ctlz判断高位状态

llvm.ctlz返回输入值的前导零个数,对于i64类型:

  • 若高位(第63位)为0,前导零个数≥1
  • 若高位为1,前导零个数=0
    只需判断llvm.ctlz的返回值是否大于0,即可区分两种场景。

直接编写LLVM IR的插桩示例

假设待检查的i64值为%val,以下是完整IR片段:

; 1. 调用llvm.ctlz统计前导零,第二个参数i1 0表示输入不为0(若输入可能为0需额外处理)
%leading_zeros = call i64 @llvm.ctlz.i64(i64 %val, i1 0)
; 2. 比较前导零个数是否大于0(即高位为0)
%is_high_bit_zero = icmp sgt i64 %leading_zeros, 0
; 3. 根据条件分支到不同操作块
br i1 %is_high_bit_zero, label %high_bit_zero_block, label %high_bit_set_block

high_bit_zero_block:
  ; 高位为0时执行的操作,比如打印、修改值等
  ret void

high_bit_set_block:
  ; 高位为1时执行的操作
  ret void

如果%val可能为0(此时所有位均为0,高位自然为0),可先判断是否为0再处理:

%is_zero = icmp eq i64 %val, 0
br i1 %is_zero, label %high_bit_zero_block, label %check_leading_zeros

check_leading_zeros:
  %leading_zeros = call i64 @llvm.ctlz.i64(i64 %val, i1 0)
  %is_high_bit_zero = icmp sgt i64 %leading_zeros, 0
  br i1 %is_high_bit_zero, label %high_bit_zero_block, label %high_bit_set_block

用LLVM Pass(C++ API)自动插桩

若需在编译流程中自动插入检查,可通过LLVM Pass实现,核心代码片段:

// 假设待处理的Value是Val(i64类型)
LLVMContext &Ctx = Val->getContext();

// 1. 创建llvm.ctlz的函数调用
Function *CtlzFunc = Intrinsic::getDeclaration(
    Val->getModule(), Intrinsic::ctlz, {Type::getInt64Ty(Ctx)});
Value *LeadingZeros = CallInst::Create(
    CtlzFunc, {Val, ConstantInt::get(Type::getInt1Ty(Ctx), 0)}, "leading_zeros",
    cast<Instruction>(Val)->getNextNode());

// 2. 创建比较指令:判断前导零个数是否大于0
Value *IsHighBitZero = new ICmpInst(
    *LeadingZeros->getParent(), ICmpInst::ICMP_SGT, LeadingZeros,
    ConstantInt::get(Type::getInt64Ty(Ctx), 0), "is_high_bit_zero");

// 3. 创建分支和新基本块
BasicBlock *OrigBB = IsHighBitZero->getParent();
Function *F = OrigBB->getParent();

BasicBlock *ZeroBB = BasicBlock::Create(Ctx, "high_bit_zero_block", F);
BasicBlock *SetBB = BasicBlock::Create(Ctx, "high_bit_set_block", F);
BasicBlock *MergeBB = BasicBlock::Create(Ctx, "merge_block", F);

// 移除原基本块的终止指令,替换为条件分支
OrigBB->getTerminator()->eraseFromParent();
BranchInst::Create(ZeroBB, SetBB, IsHighBitZero, OrigBB);

// 在ZeroBB中添加高位为0的操作(示例:可替换为自定义逻辑)
IRBuilder<> ZeroBuilder(ZeroBB);
ZeroBuilder.CreateBr(MergeBB);

// 在SetBB中添加高位为1的操作
IRBuilder<> SetBuilder(SetBB);
SetBuilder.CreateBr(MergeBB);

// 将原基本块的后续指令移到MergeBB,保证流程连贯
OrigBB->getInstList().splice(MergeBB->begin(), OrigBB->getInstList(),
                              std::next(OrigBB->begin(), OrigBB->size()));
BranchInst::Create(MergeBB, OrigBB);

注意事项

  • llvm.ctlz的第二个参数为i1类型:设为1时允许输入为0,此时输入0返回值为64(i64类型的位数);设为0时输入0的行为未定义。若输入可能为0,建议将第二个参数设为1,此时leading_zeros > 0依然成立(64>0),无需额外判断。
  • 插桩位置需选在目标Value被定义后的合适位置,确保检查时机符合需求。

内容的提问来源于stack exchange,提问作者Mohannad Ismail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:35:29