c++ - How to change the operand type in the instruction from 32bit to 64bit in LLVM?
问题描述
I am a newbie to LLVM. And I am trying to change the type of the loop variable (PHINode). For example, I have an IR as follows:
for.cond1.preheader: ; preds = %entry, %for.inc15
%k.03 = phi i32 [ 0, %entry ], [ %inc16, %for.inc15 ]
br label %for.cond4.preheader
for.cond4.preheader: ; preds = %for.cond1.preheader, %for.inc12
%indvars.iv5 = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next6, %for.inc12 ]
br label %for.body6
for.body6: ; preds = %for.cond4.preheader, %for.body6
......
%add7 = add nsw i32 %2, 1
......
for.inc12: ; preds = %for.body6
......
for.inc15: ; preds = %for.inc12
%inc16 = add nuw nsw i32 %k.03, 1
%exitcond9 = icmp ne i32 %inc16, 100
br i1 %exitcond9, label %for.cond1.preheader, label %for.end17, !llvm.loop !7
I want to change the type of the variable %k.03, hoping it will change from 32bit to 64bit. And recursively change all its references (Uses) to 64bit. The effect is as follows:
for.cond1.preheader: ; preds = %entry, %for.inc15
%k.03 = phi i64 [ 0, %entry ], [ %inc16, %for.inc15 ]
br label %for.cond4.preheader
for.cond4.preheader: ; preds = %for.cond1.preheader, %for.inc12
%indvars.iv5 = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next6, %for.inc12 ]
br label %for.body6
for.body6: ; preds = %for.cond4.preheader, %for.body6
......
%add7 = add nsw i32 %2, 1
......
for.inc12: ; preds = %for.body6
......
for.inc15: ; preds = %for.inc12
%inc16 = add nuw nsw i64 %k.03, 1
%exitcond9 = icmp ne i64 %inc16, 100
br i1 %exitcond9, label %for.cond1.preheader, label %for.end17, !llvm.loop !7
Then my approach is as follows:
static void __ChangeInsTo64Bit(User *inst) {
if (!std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "br")) {
return;
}
if (std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "icmp")) {
inst->mutateType(inst->getType()->getWithNewBitWidth(64));
}
for (auto OI = inst->op_begin(), OE = inst->op_end(); OI != OE; ++OI) {
Value *val = *OI;
val->mutateType(val->getType()->getWithNewBitWidth(64));
LLVM_DEBUG(dbgs() << "The Operand is: " << val->getName()
<< "; The bitwidth is: " << val->getType()->getIntegerBitWidth() << "\n");
}
}
static void __ChangePHINodeWidthTo64(Loop *OuterLoop, ScalarEvolution *SE) {
PHINode *OuterPHINode = OuterLoop->getInductionVariable(*SE);
if (!OuterPHINode) {
return ;
}
unsigned int outerPHIWidth = OuterPHINode->getType()->getIntegerBitWidth();
if (outerPHIWidth == 32) {
__ChangeInsTo64Bit(OuterPHINode);
for (User* user : OuterPHINode->users()) {
__ChangeInsTo64Bit(user);
for (User* u : user->users()) {
__ChangeInsTo64Bit(u);
}
}
}
}
Through the above code, I can achieve my goal, but weirdly modify the data type in the basic block for.body6:
%add7 = add nsw i32 %2, i64 1
This will cause program errors. Can someone help me point out the wrong point in my approach or provide the correct approach?
解决方案
if (!std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "br")) {
return;
}
if (std::strcmp(cast<Instruction>(inst)->getOpcodeName(), "icmp")) {
inst->mutateType(inst->getType()->getWithNewBitWidth(64));
}
这似乎是一种非常笨拙且容易出错的 RTTI 方式,尤其是因为 LLVM 提供了isa<>
用于该目的的模板。
举个例子,“icmp”检查将匹配所有不是icmp 的内容(因为!
条件前面没有),我希望这不是您的本意。
至少,以下内容等同于您的代码并且更清晰:
if (isa<BranchInst>(inst)) {
return;
}
if (!isa<ICmpInst>(inst)) {
inst->mutateType(inst->getType()->getWithNewBitWidth(64));
}
在第二个测试之前删除否定应该至少解决您的部分问题。
推荐阅读
- angular - ngFor中的Angular 8 Reset Select选项
- javascript - 为什么这个在 Javascript 中重复出现的函数不起作用?
- json - 在一次调用中更新多个路径
- node.js - 如何在嵌套 js 中为 DTO 设置默认值?
- sql - 在 sql gcp 上提取时间
- c# - System.ComponentModel.DataAnnotations 属性无法识别。无法使用 StringLength 属性验证空字符串
- ios - React 本机性能模拟器与真实设备
- php - 已弃用:非静态方法 Category::objdb() 不应在第 246 行的 /home4/muqit117/kharredo.com/admin/models/Category.php 中静态调用
- powershell - 用于收集主机名的 PowerShell Ping 脚本
- python - 用 C++ 实现 CNN 深度学习模型