[LLVMbugs] [Bug 6222] New: Assert "getTerminator returned null" for a verified function

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Wed Feb 3 09:48:08 PST 2010


http://llvm.org/bugs/show_bug.cgi?id=6222

           Summary: Assert "getTerminator returned null" for a verified
                    function
           Product: new-bugs
           Version: trunk
          Platform: Macintosh
               URL: http://xlr.sf.net
        OS/Version: MacOS X
            Status: NEW
          Keywords: crash-on-invalid, regression
          Severity: normal
          Priority: P2
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: christophe at taodyne.com
                CC: llvmbugs at cs.uiuc.edu


This is exposed by test 02.Data/rects.xl in the test suite of the XL compiler.

We generate functions by exploring a tree of possibilities. In some cases, we
will drop code that we generated. This may result in a basic block that is not
properly terminated. This passes "verifyFunction" but then asserts in
JIT::getPointerToFunction.

The stack trace for the assert is:

#0  llvm::SuccIterator<llvm::TerminatorInst*, llvm::BasicBlock>::SuccIterator
(this=0x7fff5fbfd4a0, T=0x0) at CFG.h:99
#1  0x0000000100682e0f in llvm::succ_begin (BB=0x1022bbb80) at CFG.h:204
#2  0x0000000100696379 in llvm::GraphTraits<llvm::BasicBlock*>::child_begin
(N=0x1022bbb80) at CFG.h:231
#3  0x000000010083bc4d in llvm::DFSPass<llvm::GraphTraits<llvm::BasicBlock*> >
(DT=@0x1022263c0, V=0x1022bbb80, N=0) at DominatorInternals.h:65
#4  0x000000010083bfb3 in llvm::Calculate<llvm::Function, llvm::BasicBlock*>
(DT=@0x1022263c0, F=@0x1022bbaa0) at DominatorInternals.h:253
#5  0x000000010083c6a1 in
llvm::DominatorTreeBase<llvm::BasicBlock>::recalculate<llvm::Function>
(this=0x1022263c0, F=@0x1022bbaa0) at Dominators.h:671
#6  0x000000010083319b in llvm::DominatorTree::runOnFunction (this=0x102226390,
F=@0x1022bbaa0) at Dominators.cpp:58
#7  0x00000001008932f2 in llvm::FPPassManager::runOnFunction (this=0x102224bd0,
F=@0x1022bbaa0) at PassManager.cpp:1348
#8  0x0000000100894f65 in llvm::FunctionPassManagerImpl::run (this=0x102224660,
F=@0x1022bbaa0) at PassManager.cpp:1300
#9  0x0000000100895114 in llvm::FunctionPassManager::run (this=0x102223ca0,
F=@0x1022bbaa0) at PassManager.cpp:1230
#10 0x00000001005039d3 in llvm::JIT::runJITOnFunctionUnlocked
(this=0x102224560, F=0x1022ccef0, locked=@0x7fff5fbfdb00) at JIT.cpp:642
#11 0x0000000100503c72 in llvm::JIT::getPointerToFunction (this=0x102224560,
F=0x1022ccef0) at JIT.cpp:680
#12 0x000000010003e5ea in XL::CompiledUnit::Finalize (this=0x7fff5fbfdbe0) at
compiler.cpp:599

The basic block being looked at contains the following:

p debugv(BB)

allocas:
  %result = alloca %tree*                         ; <%tree**> [#uses=3]
  store %tree* %0, %tree** %result
  %loc1 = alloca %tree*                           ; <%tree**> [#uses=1]
  %loc2 = alloca %tree*                           ; <%tree**> [#uses=4]
  %computed = alloca i1                           ; <i1*> [#uses=4]
  store i1 false, i1* %computed
  %loc3 = alloca %tree*                           ; <%tree**> [#uses=1]
  %loc4 = alloca %tree*                           ; <%tree**> [#uses=1]
  %treek = load %tree** @xlcst7                   ; <%tree*> [#uses=2]
  store %tree* %treek, %tree** %loc2
  %loc6 = alloca %tree*                           ; <%tree**> [#uses=2]
  %computed7 = alloca i1                          ; <i1*> [#uses=3]
  store i1 false, i1* %computed7
  %loc12 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed15 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed15
  %loc17 = alloca %tree*                          ; <%tree**> [#uses=6]
  store %tree* %1, %tree** %loc17
  %loc22 = alloca %tree*                          ; <%tree**> [#uses=9]
  %computed23 = alloca i1                         ; <i1*> [#uses=7]
  store i1 false, i1* %computed23
  %loc29 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed30 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed30
  %loc31 = alloca %tree*                          ; <%tree**> [#uses=4]
  %computed34 = alloca i1                         ; <i1*> [#uses=9]
  store i1 false, i1* %computed34
  %loc36 = alloca %tree*                          ; <%tree**> [#uses=20]
  store %tree* %2, %tree** %loc36
  %loc44 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed45 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed45
  %treek49 = load %tree** @xlcst9                 ; <%tree*> [#uses=2]
  store %tree* %treek49, %tree** %loc22
  %loc55 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed56 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed56
  %loc68 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed69 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed69
  %treek87 = load %tree** @xlcst14                ; <%tree*> [#uses=2]
  store %tree* %treek87, %tree** %loc6

The function doesn't really look like it uses that basic block anymore:

define internal %tree* @xl_eval15(%tree*, %tree*) {
allocas:
  %treek = load %tree** @xlcst17                  ; <%tree*> [#uses=1]
  %treek71 = load %tree** @xlcst20                ; <%tree*> [#uses=0]
  %glob = load %tree** @xlint16                   ; <%tree*> [#uses=1]
  %2 = tail call %tree* @xl_eval4(%tree* %treek, %tree* %1, %tree* %glob) ;
<%tree*> [#uses=1]
  %3 = tail call %tree* @xl_evaluate(%tree* %2)   ; <%tree*> [#uses=0]
  %glob80 = load %tree** @xlcst19                 ; <%tree*> [#uses=1]
  %4 = tail call %tree* (%tree*, i32, ...)* @xl_new_closure(%tree* %glob80, i32
1, %tree* %1) ; <%tree*> [#uses=1]
  %glob83 = load %tree** @xlcst20                 ; <%tree*> [#uses=1]
  %glob85 = load %tree** @xlint22                 ; <%tree*> [#uses=1]
  %5 = tail call %tree* @xl_eval3(%tree* %glob83, %tree* %4, %tree* %glob85) ;
<%tree*> [#uses=1]
  %6 = tail call %tree* @xl_evaluate(%tree* %5)   ; <%tree*> [#uses=1]
  %7 = tail call %tree* @xl_evaluate(%tree* %6)   ; <%tree*> [#uses=1]
  ret %tree* %7
}

Before optimizations, it looked like:

define internal %tree* @xl_eval15(%tree*, %tree*) {
allocas:
  %result = alloca %tree*                         ; <%tree**> [#uses=4]
  store %tree* %0, %tree** %result
  %loc1 = alloca %tree*                           ; <%tree**> [#uses=5]
  %loc2 = alloca %tree*                           ; <%tree**> [#uses=4]
  %computed = alloca i1                           ; <i1*> [#uses=4]
  store i1 false, i1* %computed
  %loc3 = alloca %tree*                           ; <%tree**> [#uses=1]
  %treek = load %tree** @xlcst17                  ; <%tree*> [#uses=2]
  store %tree* %treek, %tree** %loc2
  %loc5 = alloca %tree*                           ; <%tree**> [#uses=8]
  %computed6 = alloca i1                          ; <i1*> [#uses=7]
  store i1 false, i1* %computed6
  %loc11 = alloca %tree*                          ; <%tree**> [#uses=5]
  %computed12 = alloca i1                         ; <i1*> [#uses=4]
  store i1 false, i1* %computed12
  %loc19 = alloca %tree*                          ; <%tree**> [#uses=1]
  %computed20 = alloca i1                         ; <i1*> [#uses=2]
  store i1 false, i1* %computed20
  %loc21 = alloca %tree*                          ; <%tree**> [#uses=2]
  %computed24 = alloca i1                         ; <i1*> [#uses=5]
  store i1 false, i1* %computed24
  %loc26 = alloca %tree*                          ; <%tree**> [#uses=10]
  store %tree* %1, %tree** %loc26
  %loc32 = alloca %tree*                          ; <%tree**> [#uses=1]
  %computed33 = alloca i1                         ; <i1*> [#uses=2]
  store i1 false, i1* %computed33
  %treek38 = load %tree** @xlcst19                ; <%tree*> [#uses=2]
  store %tree* %treek38, %tree** %loc11
  %loc44 = alloca %tree*                          ; <%tree**> [#uses=1]
  %computed45 = alloca i1                         ; <i1*> [#uses=2]
  store i1 false, i1* %computed45
  %loc57 = alloca %tree*                          ; <%tree**> [#uses=1]
  %computed58 = alloca i1                         ; <i1*> [#uses=2]
  store i1 false, i1* %computed58
  %treek71 = load %tree** @xlcst20                ; <%tree*> [#uses=2]
  store %tree* %treek71, %tree** %loc5
  %loc76 = alloca %tree*                          ; <%tree**> [#uses=2]
  %2 = load %tree** @xlcst19                      ; <%tree*> [#uses=1]
  store %tree* %2, %tree** %loc76
  %loc81 = alloca %tree*                          ; <%tree**> [#uses=3]
  %3 = load %tree** @xlcst19                      ; <%tree*> [#uses=1]
  store %tree* %3, %tree** %loc81
  %computed89 = alloca i1                         ; <i1*> [#uses=3]
  store i1 false, i1* %computed89
  %computed92 = alloca i1                         ; <i1*> [#uses=2]
  store i1 false, i1* %computed92
  br label %entry

entry:                                            ; preds = %allocas
  %loc = load %tree** %result                     ; <%tree*> [#uses=1]
  store %tree* %loc, %tree** %loc1
  %lazy = load i1* %computed                      ; <i1> [#uses=1]
  br i1 %lazy, label %skip, label %work

exit:                                             ; preds = %skip7
  %retval = load %tree** %result                  ; <%tree*> [#uses=1]
  ret %tree* %retval

skip:                                             ; preds = %empty, %subexpr,
%entry
  %loc4 = load %tree** %loc2                      ; <%tree*> [#uses=1]
  %4 = call %tree* @xl_evaluate(%tree* %loc4)     ; <%tree*> [#uses=1]
  store %tree* %4, %tree** %loc2
  store i1 true, i1* %computed
  %lazy9 = load i1* %computed6                    ; <i1> [#uses=1]
  br i1 %lazy9, label %skip7, label %work8

work:                                             ; preds = %entry
  br label %subexpr

subexpr:                                          ; preds = %work
  store %tree* %1, %tree** %loc3
  %intk = load %tree** @xlint16                   ; <%tree*> [#uses=0]
  %glob = load %tree** @xlint16                   ; <%tree*> [#uses=1]
  %5 = call %tree* @xl_eval4(%tree* %treek, %tree* %1, %tree* %glob) ; <%tree*>
[#uses=1]
  store %tree* %5, %tree** %loc2
  store i1 true, i1* %computed
  br label %skip

empty:                                            ; No predecessors!
  br label %skip

skip7:                                            ; preds = %empty86,
%subexpr78, %skip
  %loc87 = load %tree** %loc5                     ; <%tree*> [#uses=1]
  %6 = call %tree* @xl_evaluate(%tree* %loc87)    ; <%tree*> [#uses=1]
  store %tree* %6, %tree** %loc5
  store i1 true, i1* %computed6
  %loc88 = load %tree** %loc5                     ; <%tree*> [#uses=1]
  store %tree* %loc88, %tree** %loc1
  store i1 true, i1* %computed89
  %loc90 = load %tree** %loc1                     ; <%tree*> [#uses=1]
  %7 = call %tree* @xl_evaluate(%tree* %loc90)    ; <%tree*> [#uses=1]
  store %tree* %7, %tree** %loc1
  store i1 true, i1* %computed89
  %loc91 = load %tree** %loc1                     ; <%tree*> [#uses=1]
  store %tree* %loc91, %tree** %result
  store i1 true, i1* %computed92
  br label %exit

work8:                                            ; preds = %skip
  br label %subexpr78

subexpr10:                                        ; No predecessors!
  %lazy15 = load i1* %computed12                  ; <i1> [#uses=1]
  br i1 %lazy15, label %skip13, label %work14

skip13:                                           ; preds = %fail53, %isGood62,
%isGood37, %subexpr10
  %loc67 = load %tree** %loc11                    ; <%tree*> [#uses=1]
  %tagPtr = getelementptr %tree* %loc67, i32 0, i32 0 ; <i64*> [#uses=1]
  %tag = load i64* %tagPtr                        ; <i64> [#uses=1]
  %tagAndMask = and i64 %tag, 7                   ; <i64> [#uses=1]
  %isRightTag = icmp eq i64 %tagAndMask, 0        ; <i1> [#uses=1]
  br i1 %isRightTag, label %isRightKind, label %fail66

work14:                                           ; preds = %subexpr10
  br label %subexpr16

subexpr16:                                        ; preds = %work14
  %glob17 = load %tree** @integer                 ; <%tree*> [#uses=0]
  %glob18 = load %tree** @integer                 ; <%tree*> [#uses=1]
  store %tree* %glob18, %tree** %loc19
  store i1 true, i1* %computed20
  store %tree* %1, %tree** %loc21
  %lazy25 = load i1* %computed24                  ; <i1> [#uses=1]
  br i1 %lazy25, label %skip22, label %work23

skip22:                                           ; preds = %work23, %subexpr16
  %loc28 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %glob29 = load %tree** @integer                 ; <%tree*> [#uses=1]
  %8 = call i1 @xl_type_check(%tree* %loc28, %tree* %glob29) ; <i1> [#uses=1]
  br i1 %8, label %isGood, label %fail

work23:                                           ; preds = %subexpr16
  %loc27 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %9 = call %tree* @xl_evaluate(%tree* %loc27)    ; <%tree*> [#uses=1]
  store %tree* %9, %tree** %loc26
  store i1 true, i1* %computed24
  br label %skip22

fail:                                             ; preds = %isGood, %skip22
  br label %subexpr41

isGood:                                           ; preds = %skip22
  %glob30 = load %tree** @integer                 ; <%tree*> [#uses=0]
  %glob31 = load %tree** @integer                 ; <%tree*> [#uses=1]
  store %tree* %glob31, %tree** %loc32
  store i1 true, i1* %computed33
  %intk34 = load %tree** @xlint18                 ; <%tree*> [#uses=0]
  %glob35 = load %tree** @xlint18                 ; <%tree*> [#uses=1]
  %glob36 = load %tree** @integer                 ; <%tree*> [#uses=1]
  %10 = call i1 @xl_type_check(%tree* %glob35, %tree* %glob36) ; <i1> [#uses=1]
  br i1 %10, label %isGood37, label %fail

isGood37:                                         ; preds = %isGood
  %loc39 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %glob40 = load %tree** @xlint18                 ; <%tree*> [#uses=1]
  %11 = call %tree* @xl_BinarySubInt(%tree* %treek38, %tree* %loc39, %tree*
%glob40) ; <%tree*> [#uses=1]
  store %tree* %11, %tree** %loc11
  store i1 true, i1* %computed12
  br label %skip13

subexpr41:                                        ; preds = %fail
  %glob42 = load %tree** @real                    ; <%tree*> [#uses=0]
  %glob43 = load %tree** @real                    ; <%tree*> [#uses=1]
  store %tree* %glob43, %tree** %loc44
  store i1 true, i1* %computed45
  %loc46 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  store %tree* %loc46, %tree** %loc21
  %lazy49 = load i1* %computed24                  ; <i1> [#uses=1]
  br i1 %lazy49, label %skip47, label %work48

skip47:                                           ; preds = %work48, %subexpr41
  %loc51 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %glob52 = load %tree** @real                    ; <%tree*> [#uses=1]
  %12 = call i1 @xl_type_check(%tree* %loc51, %tree* %glob52) ; <i1> [#uses=1]
  br i1 %12, label %isGood54, label %fail53

work48:                                           ; preds = %subexpr41
  %loc50 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %13 = call %tree* @xl_evaluate(%tree* %loc50)   ; <%tree*> [#uses=1]
  store %tree* %13, %tree** %loc26
  store i1 true, i1* %computed24
  br label %skip47

fail53:                                           ; preds = %isGood54, %skip47
  br label %skip13

isGood54:                                         ; preds = %skip47
  %glob55 = load %tree** @real                    ; <%tree*> [#uses=0]
  %glob56 = load %tree** @real                    ; <%tree*> [#uses=1]
  store %tree* %glob56, %tree** %loc57
  store i1 true, i1* %computed58
  %glob59 = load %tree** @xlint18                 ; <%tree*> [#uses=0]
  %glob60 = load %tree** @xlint18                 ; <%tree*> [#uses=1]
  %glob61 = load %tree** @real                    ; <%tree*> [#uses=1]
  %14 = call i1 @xl_type_check(%tree* %glob60, %tree* %glob61) ; <i1> [#uses=1]
  br i1 %14, label %isGood62, label %fail53

isGood62:                                         ; preds = %isGood54
  %glob63 = load %tree** @xlcst19                 ; <%tree*> [#uses=1]
  %loc64 = load %tree** %loc26                    ; <%tree*> [#uses=1]
  %glob65 = load %tree** @xlint18                 ; <%tree*> [#uses=1]
  %15 = call %tree* @xl_BinarySubReal(%tree* %glob63, %tree* %loc64, %tree*
%glob65) ; <%tree*> [#uses=1]
  store %tree* %15, %tree** %loc11
  store i1 true, i1* %computed12
  br label %skip13

fail66:                                           ; preds = %isRightKind,
%skip13
  %glob72 = load %tree** @xlcst20                 ; <%tree*> [#uses=1]
  %16 = call %tree* @xl_type_error(%tree* %glob72) ; <%tree*> [#uses=1]
  store %tree* %16, %tree** %loc5
  store i1 true, i1* %computed6
  unreachable

isRightKind:                                      ; preds = %skip13
  %loc68 = load %tree** %loc11                    ; <%tree*> [#uses=1]
  %17 = bitcast %tree* %loc68 to %integer*        ; <%integer*> [#uses=1]
  %18 = getelementptr %integer* %17, i32 0, i32 4 ; <i64*> [#uses=1]
  %treeValue = load i64* %18                      ; <i64> [#uses=1]
  %isGood69 = icmp eq i64 %treeValue, 0           ; <i1> [#uses=1]
  br i1 %isGood69, label %isGood70, label %fail66

isGood70:                                         ; preds = %isRightKind
  %19 = call %tree* @xl_type_error(%tree* %treek71) ; <%tree*> [#uses=1]
  store %tree* %19, %tree** %loc5
  store i1 true, i1* %computed6
  unreachable

subexpr73:                                        ; No predecessors!
  %glob74 = load %tree** @xlcst19                 ; <%tree*> [#uses=0]
  %glob75 = load %tree** @xlcst19                 ; <%tree*> [#uses=1]
  %20 = call %tree* (%tree*, i32, ...)* @xl_new_closure(%tree* %glob75, i32 1,
%tree* %1) ; <%tree*> [#uses=1]
  store %tree* %20, %tree** %loc76
  %glob77 = load %tree** @xlcst20                 ; <%tree*> [#uses=1]
  %21 = call %tree* @xl_type_error(%tree* %glob77) ; <%tree*> [#uses=1]
  store %tree* %21, %tree** %loc5
  store i1 true, i1* %computed6
  unreachable

subexpr78:                                        ; preds = %work8
  %glob79 = load %tree** @xlcst19                 ; <%tree*> [#uses=0]
  %glob80 = load %tree** @xlcst19                 ; <%tree*> [#uses=1]
  %22 = call %tree* (%tree*, i32, ...)* @xl_new_closure(%tree* %glob80, i32 1,
%tree* %1) ; <%tree*> [#uses=1]
  store %tree* %22, %tree** %loc81
  %intk82 = load %tree** @xlint22                 ; <%tree*> [#uses=0]
  %glob83 = load %tree** @xlcst20                 ; <%tree*> [#uses=1]
  %loc84 = load %tree** %loc81                    ; <%tree*> [#uses=1]
  %glob85 = load %tree** @xlint22                 ; <%tree*> [#uses=1]
  %23 = call %tree* @xl_eval3(%tree* %glob83, %tree* %loc84, %tree* %glob85) ;
<%tree*> [#uses=1]
  store %tree* %23, %tree** %loc5
  store i1 true, i1* %computed6
  br label %skip7

empty86:                                          ; No predecessors!
  br label %skip7
}


I will fix my side (making sure there is a terminator), but I think that
verifyFunction should have caught it. Also, I am pretty sure that the same
input used to work, although due to numerous incompatible changes in the LLVM
source-code, I have not been able to do a full regression analysis.


-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list