1; RUN: opt < %s -O1 -S | FileCheck %s
2
3; The attribute nomerge prevents the 3 bar() calls from being sunk/hoisted into
4; one inside a function. Check that there are still 3 tail calls.
5
6; Test case for preventing sinking
7; CHECK-LABEL: define void @sink
8; CHECK: if.then:
9; CHECK-NEXT: tail call void @bar()
10; CHECK: if.then2:
11; CHECK-NEXT: tail call void @bar()
12; CHECK: if.end3:
13; CHECK-NEXT: tail call void @bar()
14define void @sink(i32 %i) {
15entry:
16  switch i32 %i, label %if.end3 [
17    i32 5, label %if.then
18    i32 7, label %if.then2
19  ]
20
21if.then:
22  tail call void @bar() #0
23  br label %if.end3
24
25if.then2:
26  tail call void @bar() #0
27  br label %if.end3
28
29if.end3:
30  tail call void @bar() #0
31  ret void
32}
33
34; Test case for preventing hoisting
35; CHECK-LABEL: define void @hoist
36; CHECK: if.then:
37; CHECK-NEXT: tail call void @bar()
38; CHECK: if.then2:
39; CHECK-NEXT: tail call void @bar()
40; CHECK: if.end:
41; CHECK-NEXT: tail call void @bar()
42define void @hoist(i32 %i) {
43entry:
44  %i.addr = alloca i32, align 4
45  store i32 %i, i32* %i.addr, align 4
46  %0 = load i32, i32* %i.addr, align 4
47  %cmp = icmp eq i32 %0, 5
48  br i1 %cmp, label %if.then, label %if.else
49
50if.then:
51  tail call void @bar() #1
52  unreachable
53
54if.else:
55  %1 = load i32, i32* %i.addr, align 4
56  %cmp1 = icmp eq i32 %i, 7
57  br i1 %cmp1, label %if.then2, label %if.end
58
59if.then2:
60  tail call void @bar() #1
61  unreachable
62
63if.end:
64  tail call void @bar() #1
65  unreachable
66}
67
68declare void @bar()
69
70attributes #0 = { nomerge }
71attributes #1 = { noreturn nomerge }
72