xref: /llvm-project/llvm/test/Transforms/IROutliner/mismatched-phi-outputs-ordering.ll (revision f4b925ee7078f058602fd323e25f45f1ae91ca34)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
2; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
3
4; Show that we do not extract similar regions that would involve the splitting
5; of phi nodes on exit.
6
7define void @function1(ptr %a, ptr %b) {
8entry:
9  %0 = alloca i32, align 4
10  %c = load i32, ptr %0, align 4
11  br label %test1
12test1:
13  %e = load i32, ptr %0, align 4
14  br i1 true, label %first, label %test
15test:
16  %d = load i32, ptr %0, align 4
17  br i1 true, label %first, label %next
18first:
19  %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
20  ret void
21next:
22  %2 = add i32 %d, 1
23  %3 = add i32 %e, 1
24  ret void
25}
26
27define void @function2(ptr %a, ptr %b) {
28entry:
29  %0 = alloca i32, align 4
30  %c = load i32, ptr %0, align 4
31  br label %test1
32test1:
33  %e = load i32, ptr %0, align 4
34  br i1 true, label %first, label %test
35test:
36  %d = load i32, ptr %0, align 4
37  br i1 true, label %first, label %next
38first:
39  ret void
40next:
41  %1 = add i32 %d, 1
42  %2 = add i32 %e, 1
43  ret void
44}
45; CHECK-LABEL: @function1(
46; CHECK-NEXT:  entry:
47; CHECK-NEXT:    [[DOTCE_LOC:%.*]] = alloca i32, align 4
48; CHECK-NEXT:    [[D_LOC:%.*]] = alloca i32, align 4
49; CHECK-NEXT:    [[E_LOC:%.*]] = alloca i32, align 4
50; CHECK-NEXT:    [[TMP0:%.*]] = alloca i32, align 4
51; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[E_LOC]])
52; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[D_LOC]])
53; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[DOTCE_LOC]])
54; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr [[DOTCE_LOC]], i32 0)
55; CHECK-NEXT:    [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 4
56; CHECK-NEXT:    [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 4
57; CHECK-NEXT:    [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
58; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[E_LOC]])
59; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[D_LOC]])
60; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[DOTCE_LOC]])
61; CHECK-NEXT:    br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
62; CHECK:       first:
63; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
64; CHECK-NEXT:    ret void
65; CHECK:       next:
66; CHECK-NEXT:    call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])
67; CHECK-NEXT:    ret void
68;
69;
70; CHECK-LABEL: @function2(
71; CHECK-NEXT:  entry:
72; CHECK-NEXT:    [[D_LOC:%.*]] = alloca i32, align 4
73; CHECK-NEXT:    [[E_LOC:%.*]] = alloca i32, align 4
74; CHECK-NEXT:    [[TMP0:%.*]] = alloca i32, align 4
75; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[E_LOC]])
76; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[D_LOC]])
77; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr null, i32 1)
78; CHECK-NEXT:    [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 4
79; CHECK-NEXT:    [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 4
80; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[E_LOC]])
81; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[D_LOC]])
82; CHECK-NEXT:    br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
83; CHECK:       first:
84; CHECK-NEXT:    ret void
85; CHECK:       next:
86; CHECK-NEXT:    call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])
87; CHECK-NEXT:    ret void
88;
89;
90; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
91; CHECK-NEXT:  newFuncRoot:
92; CHECK-NEXT:    br label [[ENTRY_TO_OUTLINE:%.*]]
93; CHECK:       entry_to_outline:
94; CHECK-NEXT:    [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
95; CHECK-NEXT:    br label [[TEST1:%.*]]
96; CHECK:       test1:
97; CHECK-NEXT:    [[E:%.*]] = load i32, ptr [[TMP0]], align 4
98; CHECK-NEXT:    br i1 true, label [[FIRST_SPLIT:%.*]], label [[TEST:%.*]]
99; CHECK:       test:
100; CHECK-NEXT:    [[D:%.*]] = load i32, ptr [[TMP0]], align 4
101; CHECK-NEXT:    br i1 true, label [[FIRST_SPLIT]], label [[NEXT_EXITSTUB:%.*]]
102; CHECK:       first.split:
103; CHECK-NEXT:    [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST]] ], [ [[E]], [[TEST1]] ]
104; CHECK-NEXT:    br label [[FIRST_EXITSTUB:%.*]]
105; CHECK:       first.exitStub:
106; CHECK-NEXT:    switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_1:%.*]] [
107; CHECK-NEXT:    i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
108; CHECK-NEXT:    i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]
109; CHECK-NEXT:    ]
110; CHECK:       next.exitStub:
111; CHECK-NEXT:    switch i32 [[TMP4]], label [[FINAL_BLOCK_0:%.*]] [
112; CHECK-NEXT:    i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
113; CHECK-NEXT:    i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]
114; CHECK-NEXT:    ]
115; CHECK:       output_block_0_0:
116; CHECK-NEXT:    store i32 [[E]], ptr [[TMP1:%.*]], align 4
117; CHECK-NEXT:    store i32 [[D]], ptr [[TMP2:%.*]], align 4
118; CHECK-NEXT:    br label [[FINAL_BLOCK_0]]
119; CHECK:       output_block_0_1:
120; CHECK-NEXT:    store i32 [[E]], ptr [[TMP1]], align 4
121; CHECK-NEXT:    store i32 [[DOTCE]], ptr [[TMP3:%.*]], align 4
122; CHECK-NEXT:    br label [[FINAL_BLOCK_1]]
123; CHECK:       output_block_1_0:
124; CHECK-NEXT:    store i32 [[E]], ptr [[TMP1]], align 4
125; CHECK-NEXT:    store i32 [[D]], ptr [[TMP2]], align 4
126; CHECK-NEXT:    br label [[FINAL_BLOCK_0]]
127; CHECK:       output_block_1_1:
128; CHECK-NEXT:    store i32 [[E]], ptr [[TMP1]], align 4
129; CHECK-NEXT:    br label [[FINAL_BLOCK_1]]
130; CHECK:       final_block_0:
131; CHECK-NEXT:    ret i1 false
132; CHECK:       final_block_1:
133; CHECK-NEXT:    ret i1 true
134;
135;
136; CHECK-LABEL: @outlined_ir_func_1(
137; CHECK-NEXT:  newFuncRoot:
138; CHECK-NEXT:    br label [[NEXT_TO_OUTLINE:%.*]]
139; CHECK:       next_to_outline:
140; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP0:%.*]], 1
141; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP1:%.*]], 1
142; CHECK-NEXT:    br label [[NEXT_AFTER_OUTLINE_EXITSTUB:%.*]]
143; CHECK:       next_after_outline.exitStub:
144; CHECK-NEXT:    ret void
145;
146