llvm ir optimization"在Def被销毁之后仍然停留使用"错误功能删除

时间:2017-12-02 11:15:40

标签: compilation llvm compiler-optimization jit llvm-ir

您好,我最近升级到llvm 4.0,现在我从优化器中得到了最奇怪的错误,这似乎是最好的代码。我已经确定了下面似乎给出了错误的代码,并且打印出llvm给我的关于<badref>的断言,但是在它所讨论的代码中没有<badref>。这使我认为它可能是编译器错误或生成的代码不正确。

; ModuleID = '__form__module.$static.196'
source_filename = "__form__module.$static.196"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"

%struct.clousure_type = type { void ()*, %struct.closure_vtable*, i8* }
%struct.closure_vtable = type { %struct.type_info*, void (i8*, i8*)*, void (i8*)*, i8 (i8*, i8*)*, i64 (i8*, i8*)* }
%struct.type_info = type { i8*, i8*, i64, i8, i8, i8, i8, %struct.type_info**, %struct.member_info* }
%struct.member_info = type { i8, %struct.type_info* }

@"$static.159$stub_ptr" = external hidden externally_initialized global void (%struct.clousure_type*, %struct.clousure_type*)*

define hidden void @"$static.196"(%struct.clousure_type*, %struct.clousure_type*, %struct.clousure_type*, i8) {
entry:
  %4 = icmp eq i8 %3, 0
  br i1 %4, label %bb2, label %bb4

bb2:                                              ; preds = %entry
  %5 = icmp eq %struct.clousure_type* %0, %2
  br i1 %5, label %bb3, label %bb6

bb3:                                              ; preds = %bb4, %bb2
  ret void

bb4:                                              ; preds = %entry
  %6 = icmp eq %struct.clousure_type* %1, %2
  br i1 %6, label %bb3, label %bb6

bb6:                                              ; preds = %bb4, %bb2
  tail call void @"$static.159"(%struct.clousure_type* %0, %struct.clousure_type* %1)
  ret void
}

; Function Attrs: alwaysinline
define available_externally hidden void @"$static.159"(%struct.clousure_type*, %struct.clousure_type*) #0 {
entry:
  %2 = load void (%struct.clousure_type*, %struct.clousure_type*)*, void (%struct.clousure_type*, %struct.clousure_type*)** @"$static.159$stub_ptr", align 8
  tail call void %2(%struct.clousure_type* %0, %struct.clousure_type* %1)
  ret void
}

attributes #0 = { alwaysinline }


While deleting: void (%struct.clousure_type*, %struct.clousure_type*)* %$static.159
Use still stuck around after Def is destroyed:  call void @"$static.159"(%struct.clousure_type* <badref>, %struct.clousure_type* %0)

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Assertion failed!

Program: C:\Users\RICH\workspace\formvm\Debug\formvm.exe
File: C:\llvm-4.0.0.src\lib\IR\Value.cpp, Line 85

Expression: use_empty() && "Uses remain when a value is destroyed!"

优化器正在处理的llvm ir代码,代表上面两个函数,是以下两个函数(从c ++生成)。

define private void @gen__fun__return_copy85(%struct.clousure_type*, %struct.clousure_type*, %struct.clousure_type*, i8) {
entry:
  %4 = alloca %struct.clousure_type*, align 8
  store %struct.clousure_type* %0, %struct.clousure_type** %4, align 8
  %5 = load %struct.clousure_type*, %struct.clousure_type** %4, align 8
  %6 = alloca %struct.clousure_type*, align 8
  store %struct.clousure_type* %1, %struct.clousure_type** %6, align 8
  %7 = load %struct.clousure_type*, %struct.clousure_type** %6, align 8
  %8 = alloca %struct.clousure_type*, align 8
  store %struct.clousure_type* %2, %struct.clousure_type** %8, align 8
  %9 = load %struct.clousure_type*, %struct.clousure_type** %8, align 8
  %10 = alloca i8, align 8
  store i8 %3, i8* %10, align 8
  %11 = load i8, i8* %10, align 8
  %12 = icmp eq i8 %11, 0
  br i1 %12, label %bb2, label %bb4

bb2:                                              ; preds = %entry
  %13 = icmp eq %struct.clousure_type* %5, %9
  br i1 %13, label %bb3, label %bb6

bb3:                                              ; preds = %bb2
  ret void

bb4:                                              ; preds = %entry
  %14 = icmp eq %struct.clousure_type* %7, %9
  br i1 %14, label %bb5, label %bb6

bb5:                                              ; preds = %bb4
  ret void

bb6:                                              ; preds = %bb4, %bb2
  call void @_ZN13clousure_typeC2ERKS_(%struct.clousure_type* %5, %struct.clousure_type* %7)
  ret void
}

define private void @_ZN13clousure_typeC2ERKS_(%struct.clousure_type* %this, %struct.clousure_type* %rhs) {
  %1 = alloca %struct.clousure_type*, align 8
  %2 = alloca %struct.clousure_type*, align 8
  store %struct.clousure_type* %this, %struct.clousure_type** %1, align 8
  store %struct.clousure_type* %rhs, %struct.clousure_type** %2, align 8
  %3 = load %struct.clousure_type*, %struct.clousure_type** %1, align 8
  %4 = getelementptr %struct.clousure_type, %struct.clousure_type* %3, i32 0, i32 0
  store void ()* null, void ()** %4, align 8
  %5 = getelementptr %struct.clousure_type, %struct.clousure_type* %3, i32 0, i32 1
  store %struct.closure_vtable* null, %struct.closure_vtable** %5, align 8
  %6 = getelementptr %struct.clousure_type, %struct.clousure_type* %3, i32 0, i32 2
  store i8* null, i8** %6, align 8
  %7 = load %struct.clousure_type*, %struct.clousure_type** %2, align 8
  call void @_ZN13clousure_type4copyERKS_(%struct.clousure_type* %3, %struct.clousure_type* %7)
  ret void
}

要添加以下传递,我是否需要更改任何添加,哪些可能导致问题?

    FPM->add(llvm::createCFGSimplificationPass());
    FPM->add(llvm::createInstructionCombiningPass());
    FPM->add(llvm::createPromoteMemoryToRegisterPass());
    FPM->add(llvm::createCFGSimplificationPass());
    FPM->add(llvm::createLICMPass());
    FPM->add(llvm::createLoopDeletionPass());
    FPM->add(llvm::createLoopUnrollPass());
    FPM->add(llvm::createSCCPPass());
    FPM->add(llvm::createCFGSimplificationPass());
    FPM->add(llvm::createInstructionCombiningPass());
    FPM->add(llvm::createDeadStoreEliminationPass());
    FPM->add(llvm::createAggressiveDCEPass());
    FPM->add(llvm::createCFGSimplificationPass());
    FPM->add(llvm::createTailCallEliminationPass());

编辑即使我删除了所有的传递,我仍然会收到错误!

目前似乎问题源于以下函数@"$static.159",而不是函数尝试load @"$static.159$stub_ptr"。理论是它无法在尝试加载自身时将其删除?

; Function Attrs: alwaysinline
define available_externally hidden void @"$static.159"(%struct.clousure_type*, %struct.clousure_type*) #0 {
entry:
  %2 = load void (%struct.clousure_type*, %struct.clousure_type*)*, void (%struct.clousure_type*, %struct.clousure_type*)** @"$static.159$stub_ptr"
  tail call void %2(%struct.clousure_type* %0, %struct.clousure_type* %1)
  ret void
}

1 个答案:

答案 0 :(得分:0)

升级到llvm 5.0以最终处理此错误。

这不是理论上的问题。简单地放入我在函数指针中存储的函数之一,由于生成上述代码的c ++代码中的错误初始化指针导致上面找到的<badref>,因此没有生成alloca。请注意,<badref>仅在稍后由于使用函数指针而被优化器找到!!

为什么这个指针不会导致早期的段错误我不知道,但它没有,允许不正确的代码生成。在llvm 5.0上,指针按预期给出了段错误,允许我找到错误。