reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
; RUN: opt -inline -S < %s | FileCheck %s
; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
; PR10162

; Make sure doit is not inlined since the blockaddress is taken
; which could be unsafe
; CHECK: store i8* blockaddress(@doit, %here), i8** %pptr, align 8

@i = global i32 1, align 4
@ptr1 = common global i8* null, align 8

define void @doit(i8** nocapture %pptr, i32 %cond) nounwind uwtable {
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.end, label %here

here:
  store i8* blockaddress(@doit, %here), i8** %pptr, align 8
  br label %if.end

if.end:
  ret void
}

define void @f(i32 %cond) nounwind uwtable {
entry:
  call void @doit(i8** @ptr1, i32 %cond)
  ret void
}

; PR27233: We can inline @run into @init.  Don't crash on it.
;
; CHECK-LABEL: define void @init
; CHECK:         store i8* blockaddress(@run, %bb)
; CHECK-SAME:        @run.bb
define void @init() {
entry:
  call void @run()
  ret void
}

define void @run() {
entry:
  store i8* blockaddress(@run, %bb), i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @run.bb, i64 0, i64 0), align 8
  ret void

bb:
  unreachable
}

@run.bb = global [1 x i8*] zeroinitializer

; Check that a function referenced by a global blockaddress wont be inlined,
; even if it contains a callbr. We might be able to relax this in the future
; as long as the global blockaddress is updated correctly.
@ba = internal global i8* blockaddress(@foo, %7), align 8
define internal i32 @foo(i32) {
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  %4 = load i32, i32* %3, align 4
  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %4, i8* blockaddress(@foo, %7), i8* blockaddress(@foo, %6)) #1
          to label %5 [label %7, label %6]

; <label>:5:                                      ; preds = %1
  store i32 0, i32* %2, align 4
  br label %8

; <label>:6:                                      ; preds = %1
  store i32 1, i32* %2, align 4
  br label %8

; <label>:7:                                      ; preds = %1
  store i32 2, i32* %2, align 4
  br label %8

; <label>:8:                                      ; preds = %7, %6, %5
  %9 = load i32, i32* %2, align 4
  ret i32 %9
}
define dso_local i32 @bar() {
  %1 = call i32 @foo(i32 0)
  ret i32 %1
}

; CHECK: define dso_local i32 @bar() {
; CHECK:   %1 = call i32 @foo(i32 0)
; CHECK:   ret i32 %1
; CHECK: }

; Triple check that even with a global aggregate whose member is a blockaddress,
; we still don't inline referred to functions.

%struct.foo = type { i8* }

@my_foo = dso_local global %struct.foo { i8* blockaddress(@baz, %7) }

define internal i32 @baz(i32) {
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  %4 = load i32, i32* %3, align 4
  callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %4, i8* blockaddress(@baz, %7), i8* blockaddress(@baz, %6)) #1
          to label %5 [label %7, label %6]

; <label>:5:                                      ; preds = %1
  store i32 0, i32* %2, align 4
  br label %8

; <label>:6:                                      ; preds = %1
  store i32 1, i32* %2, align 4
  br label %8

; <label>:7:                                      ; preds = %1
  store i32 2, i32* %2, align 4
  br label %8

; <label>:8:                                      ; preds = %7, %6, %5
  %9 = load i32, i32* %2, align 4
  ret i32 %9
}
define dso_local i32 @quux() {
  %1 = call i32 @baz(i32 0)
  ret i32 %1
}

; CHECK: define dso_local i32 @quux() {
; CHECK:   %1 = call i32 @baz(i32 0)
; CHECK:   ret i32 %1
; CHECK: }