1; RUN: opt -S < %s -jump-threading | FileCheck %s
2
3; Keep block addresses alive.
4@addresses = constant [4 x i8*] [
5  i8* blockaddress(@test1, %L1), i8* blockaddress(@test1, %L2),
6  i8* blockaddress(@test2, %L1), i8* blockaddress(@test2, %L2)
7]
8
9declare void @bar()
10declare void @baz()
11
12
13
14; Check basic jump threading for indirectbr instructions.
15
16; CHECK: void @test1
17; CHECK: br i1 %tobool, label %L1, label %indirectgoto
18; CHECK-NOT: if.else:
19; CHECK: L1:
20; CHECK: indirectbr i8* %address, [label %L1, label %L2]
21define void @test1(i32 %i, i8* %address) nounwind {
22entry:
23  %rem = srem i32 %i, 2
24  %tobool = icmp ne i32 %rem, 0
25  br i1 %tobool, label %indirectgoto, label %if.else
26
27if.else:                                          ; preds = %entry
28  br label %indirectgoto
29
30L1:                                               ; preds = %indirectgoto
31  call void @bar()
32  ret void
33
34L2:                                               ; preds = %indirectgoto
35  call void @baz()
36  ret void
37
38indirectgoto:                                     ; preds = %if.else, %entry
39  %indirect.goto.dest = phi i8* [ %address, %if.else ], [ blockaddress(@test1, %L1), %entry ]
40  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2]
41}
42
43
44; Check constant folding of indirectbr
45
46; CHECK: void @test2
47; CHECK: entry:
48; CHECK-NEXT: br label %L1
49; CHECK: L1:
50; CHECK-NEXT: call void @bar
51; CHECK-NEXT: ret void
52define void @test2() nounwind {
53entry:
54  indirectbr i8* blockaddress(@test2, %L1), [label %L1, label %L2]
55
56L1:                                               ; preds = %indirectgoto
57  call void @bar()
58  ret void
59
60L2:                                               ; preds = %indirectgoto
61  call void @baz()
62  ret void
63}
64
65
66; PR4151
67; Don't merge address-taken blocks.
68@.str = private unnamed_addr constant [4 x i8] c"%p\0A\00"
69
70; CHECK-LABEL: @test3(
71; CHECK: __here:
72; CHECK: blockaddress(@test3, %__here)
73; CHECK: __here1:
74; CHECK: blockaddress(@test3, %__here1)
75; CHECK: __here3:
76; CHECK: blockaddress(@test3, %__here3)
77define void @test3() nounwind ssp noredzone {
78entry:
79  br label %__here
80
81__here:                                           ; preds = %entry
82  %call = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here) to i64)) nounwind noredzone
83  br label %__here1
84
85__here1:                                          ; preds = %__here
86  %call2 = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here1) to i64)) nounwind noredzone
87  br label %__here3
88
89__here3:                                          ; preds = %__here1
90  %call4 = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here3) to i64)) nounwind noredzone
91  ret void
92}
93
94declare i32 @printf(...) noredzone
95