我正在编写LLVM LoopPass,在其中我需要知道哪些值 在循环外部使用。为此,我有以下代码:
virtual bool runOnLoop(Loop *loop, LPPassManager &LPM)
{
for (auto it = loop->block_begin(); it != loop->block_end(); it++)
{
for (auto inst = (*it)->begin(); inst != (*it)->end(); inst++)
{
if (Is_Used_Outside_This_loop(loop,(Instruction *) inst))
{
errs() << inst->getName().str();
errs() << " is used outside the loop\n";
}
}
}
// ...
}
内部函数乍一看似乎正确,但是下面带有* .ll文件,
它为%tmp5
提供了错误的分类,因为它被使用了两次
在循环的基本块内。
bool Is_Used_Outside_This_loop(Loop *loop, Value *v)
{
int n=0;
int numUses = v->getNumUses();
for (auto it = loop->block_begin(); it != loop->block_end(); it++)
{
if (v->isUsedInBasicBlock(*it))
{
n++;
}
}
if (n == numUses) return false;
else return true;
}
以下* .ll代码显示%tmp5
被使用了两次
在循环的基本块内。当我仔细搜索API时,
我找不到类似Value :: numUsesInBasicBlock(...)
; Function Attrs: nounwind uwtable
define internal void @foo(i8* %s) #0 {
entry:
%s.addr = alloca i8*, align 8
%c = alloca i8, align 1
store i8* %s, i8** %s.addr, align 8
store i8 0, i8* %c, align 1
br label %while.cond
while.cond: ; preds = %while.body, %entry
%tmp = load i8*, i8** %s.addr, align 8
%tmp1 = load i8, i8* %tmp, align 1
%conv = sext i8 %tmp1 to i32
%cmp = icmp eq i32 %conv, 97
br i1 %cmp, label %lor.end, label %lor.rhs
lor.rhs: ; preds = %while.cond
%tmp2 = load i8*, i8** %s.addr, align 8
%tmp3 = load i8, i8* %tmp2, align 1
%conv2 = sext i8 %tmp3 to i32
%cmp3 = icmp eq i32 %conv2, 98
br label %lor.end
lor.end:; preds = %lor.rhs, %while.cond
%tmp4 = phi i1 [ true, %while.cond ], [ %cmp3, %lor.rhs ]
br i1 %tmp4, label %while.body, label %while.end
while.body: ; preds = %lor.end
%tmp5 = load i8*, i8** %s.addr, align 8
%incdec.ptr = getelementptr inbounds i8, i8* %tmp5, i32 1
store i8* %incdec.ptr, i8** %s.addr, align 8
%tmp6 = load i8, i8* %tmp5, align 1
store i8 %tmp6, i8* %c, align 1
br label %while.cond
while.end: ; preds = %lor.end
%tmp7 = load i8*, i8** %s.addr, align 8
%tmp8 = load i8, i8* %tmp7, align 1
%conv5 = sext i8 %tmp8 to i32
%cmp6 = icmp eq i32 %conv5, 99
br i1 %cmp6, label %if.then, label %if.end
if.then: ; preds = %while.end
%tmp9 = load i8*, i8** %s.addr, align 8
%incdec.ptr8 = getelementptr inbounds i8, i8* %tmp9, i32 1
store i8* %incdec.ptr8, i8** %s.addr, align 8
br label %if.end
if.end: ; preds = %if.then, %while.end
ret void
}
很显然,必须有一种方法,对吗?谢谢!
答案 0 :(得分:0)
这是我解决的方法,尽管它看起来过于复杂:
virtual bool runOnLoop(Loop *loop, LPPassManager &LPM)
{
for (auto it = loop->block_begin(); it != loop->block_end(); it++)
{
for (auto inst = (*it)->begin(); inst != (*it)->end(); inst++)
{
int n=0;
for (auto use = inst->use_begin(); use != inst->use_end(); use++)
{
Instruction *i = (Instruction *) use->getUser();
if (BasicBlockBelongsToLoop(i->getParent(),loop))
{
n++;
}
}
assert(n <= inst->getNumUses());
if (n < inst->getNumUses())
{
errs() << inst->getName().str();
errs() << " is used outside the loop\n";
}
}
}
// ...
我也没有在API中找到如何检查基本块是否属于循环, 所以我不得不写我自己的BasicBlockBelongsToLoop,这里是:
bool BasicBlockBelongsToLoop(BasicBlock *BB, Loop *loop)
{
for (auto it = loop->block_begin(); it != loop->block_end(); it++)
{
if (BB == (*it))
{
return true;
}
}
return false;
}
答案 1 :(得分:0)
问题是您的退出条件。您要求使用,然后将其与使用该值的块数进行比较。
因此,如果在同一基本块中两次使用该值,则使用次数为2,并且使用该值的基本块的export const createPost = (postData) => async (dispatch) => {
// send postData to server
const rawResponse = await fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
});
// we are done with server but we need one more step
// turn a raw response to readable JS object
const message = await rawResponse.json()
// message from server response
console.log('Message ', message);
// store same object as we sent to server in redux store
dispatch({ type: NEW_POST, payload: postData });
}
计数器仅增加一次,因此{{1 }}和n
。
也许做一个您想要的更简洁的方法是:
n
,然后在numUses
方法中输入以下内容:
void FindUsesNotIn(
llvm::SmallPtrSetImpl<llvm::BasicBlock *> &Blocks,
llvm::SmallPtrSetImpl<llvm::Value *> &OutUses) {
for(const auto &b : Blocks)
for(auto &i : *b)
for(const auto &u : i.users()) {
auto *userInst = llvm::dyn_cast<llvm::Instruction>(u);
if(userInst && !Blocks.count(userInst->getParent())) {
OutUses.insert(&i);
break;
}
}
}