LLVM:防止DAGCombiner::RecursiveDeleteUnusedNodes删除相关SDNodes

LLVM:防止DAGCombiner::RecursiveDeleteUnusedNodes删除相关SDNodes,llvm,Llvm,我面临着一项相当具有教育意义的任务,即通过以下方式扩展LLVM: 将寄存器XACC和指令LRXACC、SRXACCarg1、XMACarg1、arg2添加到SPARC后端。操作说明如下所示: LRXACC:来自XACC的加载值, SRXACC:写入XACC, XMAC:XACC+=arg1*arg2>>31 在叮当作响的前端为所有三个部件提供内置部件。 我的测试来源是: int main() { int acc = 0; __builtin___srxacc(acc); __builtin___

我面临着一项相当具有教育意义的任务,即通过以下方式扩展LLVM:

将寄存器XACC和指令LRXACC、SRXACCarg1、XMACarg1、arg2添加到SPARC后端。操作说明如下所示: LRXACC:来自XACC的加载值, SRXACC:写入XACC, XMAC:XACC+=arg1*arg2>>31 在叮当作响的前端为所有三个部件提供内置部件。 我的测试来源是:

int main() {
int acc = 0;
__builtin___srxacc(acc);
__builtin___xmac(12345,6789);
acc = __builtin___lrxacc();
return 0;
}
我能够支持将内置函数转换为内在函数。我从clang获得的IR文件看起来不错:

define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %acc = alloca i32, align 4
  store i32 0, i32* %retval
  store i32 0, i32* %acc, align 4
  %0 = load i32* %acc, align 4
  call void @llvm.sparc.srxacc(i32 %0)
  call void @llvm.sparc.xmac(i32 12345, i32 6789)
  %1 = call i32 @llvm.sparc.lrxacc()
  store i32 %1, i32* %acc, align 4
  ret i32 0
}
问题出现在DAG组合步骤中,最终输出代码如下所示:

.text
    .file   "file22.ll"
    .globl  main
    .align  4
    .type   main,@function
   main:                                ! @main
! BB#0:                                 ! %entry
       add %sp, -104, %sp
       st %g0, [%sp+100]
       st %g0, [%sp+96]
       lrxacc %xacc, %o0
       st %o0, [%sp+96]
       sethi 0, %o0
       retl
       add %sp, 104, %sp
.Ltmp0:
       .size   main, .Ltmp0-main
       .ident  "clang version 3.6.0 (trunk)"
DAGCombiner删除冗余的srxacc和xmac指令。在::Run方法中,它检查节点是否为use\u empty,如果为use\u empty,则将其删除 合并器之所以这样做,是因为它们将结果存储在寄存器中,所以从图中看不到它们中的一个依赖于另一个。 如能就如何避免删除我的指示提出建议,我将不胜感激。 非常感谢。 编辑 为了简化和具体化:在IR代码中表示的指令,如void@llvm.sparc.srxacci32%0,在合并器看来,它们不影响计算,相应的SDNodes接收空的UseList。如何避免这种情况

您可以使用链标记来表示节点之间的控制依赖关系。这样,即使第二条指令不使用第一条指令的任何输出,也可以在两条指令之间添加伪依赖项。 您可以使用CopyToRegister和CopyFromRegister来处理预定义的物理寄存器 您可以使用Glue将几个简单指令粘合到一个复杂的伪指令中。 考虑以下为x86编译的简单示例:

int foo(int aa, int bb) {
  return aa / bb;
}
您可能还想研究更复杂的示例,尽管DAG图片太大,无法在此处发布,但您可以使用-view sched dags选项查看DAG:


也请看一看。

我刚才解决了我的问题,但谢谢你的回答。我尝试了胶水,但它带来了太多的问题。最后,帮助我的是把根作为第一个论点到处传。我的解决方案中的寄存器是特殊的,因此它们还没有在DAG创建阶段引入。对于可能感兴趣的任何人,我的解决方案如下:
void foo(int aa, int bb, int *x, int *y, int *z) {
  *x = aa / bb;
  *y = aa % bb;
  *z = aa * bb;
}