保留LLVM / LLC中的div-by-zero

时间:2015-11-27 11:55:18

标签: llvm llvm-ir

我正在为LLVM编写一个编译器,用于语义 explicity 定义除以的除法应始终引发浮点异常的语言。问题是,在我的原始IR上运行-mem2reg和-constprop后,我的代码转换为:

define i32 @main() {
entry:
 %t3 = sdiv i32 2, 0
 ret i32 7
}

然后由llc -O0转换为:

.text
.globl  _c0_main
.align  16, 0x90
.type   _c0_main,@function
main:                               
.cfi_startproc
# BB#0:                                 # %entry
  movl  $7, %eax
  ret
.Ltmp0:
  .size main, .Ltmp0-main
  .cfi_endproc

有没有办法强制公司不要删除有效的操作?

2 个答案:

答案 0 :(得分:1)

sdiv指令除以零语义,未定义。如果你的前端语言有一些定义的语义,你需要使用sdiv以外的指令。

也许你必须检测除以零,并在运行时分支给一系列指令,这些指令给出了你想要的语义。

答案 1 :(得分:0)

language reference表示科林所说的[d]ivision by zero leads to undefined behavior

因此,您必须检查被除数是否为零并显式生成浮点异常。在C中,这可能如下所示:

extern void raiseFloatingException();

int someFunc() {
    int a = 2;
    int b = 0;
    if (!b) {
        raiseFloatingException();
    }
    int result = a / b;
    return result;
}

如果您将其编译为位代码并使用-mem2reg进行优化,您将获得可以使用后端生成的模式:

define i32 @someFunc() #0 {
  %1 = icmp ne i32 0, 0
  br i1 %1, label %3, label %2

; <label>:2                                       ; preds = %0
  call void (...)* @raiseFloatingException()
  br label %3

; <label>:3                                       ; preds = %2, %0
  %4 = sdiv i32 2, 0
  ret i32 %4
}

请注意,您必须提供raiseFloatingException功能并将其与您的代码相关联。