xref: /llvm-project/llvm/test/Transforms/IROutliner/outlining-branches-phi-nodes.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; Here we have multiple exits, but the different sources, same outputs are
5; needed, this checks that they are compressed, and moved into the appropriate
6; output blocks.
7
8define void @outline_outputs1() #0 {
9entry:
10  %output = alloca i32, align 4
11  %result = alloca i32, align 4
12  %output2 = alloca i32, align 4
13  %result2 = alloca i32, align 4
14  %a = alloca i32, align 4
15  %b = alloca i32, align 4
16  br label %block_2
17block_1:
18  %a2 = alloca i32, align 4
19  %b2 = alloca i32, align 4
20  br label %block_2
21block_2:
22  %a2val = load i32, ptr %a
23  %b2val = load i32, ptr %b
24  %add2 = add i32 2, %a2val
25  %mul2 = mul i32 2, %b2val
26  br label %block_5
27block_3:
28  %aval = load i32, ptr %a
29  %bval = load i32, ptr %b
30  %add = add i32 2, %aval
31  %mul = mul i32 2, %bval
32  br label %block_4
33block_4:
34  store i32 %add, ptr %output, align 4
35  store i32 %mul, ptr %result, align 4
36  br label %block_6
37block_5:
38  store i32 %add2, ptr %output, align 4
39  store i32 %mul2, ptr %result, align 4
40  br label %block_6
41dummy:
42  ret void
43block_6:
44  %diff = phi i32 [%aval, %block_4], [%a2val, %block_5]
45  ret void
46}
47
48define void @outline_outputs2() #0 {
49entry:
50  %output = alloca i32, align 4
51  %result = alloca i32, align 4
52  %output2 = alloca i32, align 4
53  %result2 = alloca i32, align 4
54  %a = alloca i32, align 4
55  %b = alloca i32, align 4
56  br label %block_2
57block_1:
58  %a2 = alloca i32, align 4
59  %b2 = alloca i32, align 4
60  br label %block_2
61block_2:
62  %a2val = load i32, ptr %a
63  %b2val = load i32, ptr %b
64  %add2 = add i32 2, %a2val
65  %mul2 = mul i32 2, %b2val
66  br label %block_5
67block_3:
68  %aval = load i32, ptr %a
69  %bval = load i32, ptr %b
70  %add = add i32 2, %aval
71  %mul = mul i32 2, %bval
72  br label %block_4
73block_4:
74  store i32 %add, ptr %output, align 4
75  store i32 %mul, ptr %result, align 4
76  br label %block_6
77block_5:
78  store i32 %add2, ptr %output, align 4
79  store i32 %mul2, ptr %result, align 4
80  br label %block_6
81dummy:
82  ret void
83block_6:
84  %diff = phi i32 [%aval, %block_4], [%a2val, %block_5]
85  ret void
86}
87
88; CHECK-LABEL: @outline_outputs1(
89; CHECK-NEXT:  entry:
90; CHECK-NEXT:    [[DIFF_CE_LOC:%.*]] = alloca i32, align 4
91; CHECK-NEXT:    [[OUTPUT:%.*]] = alloca i32, align 4
92; CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
93; CHECK-NEXT:    [[OUTPUT2:%.*]] = alloca i32, align 4
94; CHECK-NEXT:    [[RESULT2:%.*]] = alloca i32, align 4
95; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
96; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
97; CHECK-NEXT:    br label [[BLOCK_2:%.*]]
98; CHECK:       block_1:
99; CHECK-NEXT:    [[A2:%.*]] = alloca i32, align 4
100; CHECK-NEXT:    [[B2:%.*]] = alloca i32, align 4
101; CHECK-NEXT:    br label [[BLOCK_2]]
102; CHECK:       block_2:
103; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[DIFF_CE_LOC]])
104; CHECK-NEXT:    call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[DIFF_CE_LOC]])
105; CHECK-NEXT:    [[DIFF_CE_RELOAD:%.*]] = load i32, ptr [[DIFF_CE_LOC]], align 4
106; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[DIFF_CE_LOC]])
107; CHECK-NEXT:    br label [[BLOCK_6:%.*]]
108; CHECK: dummy:
109; CHECK-NEXT:  ret void
110; CHECK:       block_6:
111; CHECK-NEXT:    [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ]
112; CHECK-NEXT:    ret void
113;
114;
115; CHECK-LABEL: @outline_outputs2(
116; CHECK-NEXT:  entry:
117; CHECK-NEXT:    [[DIFF_CE_LOC:%.*]] = alloca i32, align 4
118; CHECK-NEXT:    [[OUTPUT:%.*]] = alloca i32, align 4
119; CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
120; CHECK-NEXT:    [[OUTPUT2:%.*]] = alloca i32, align 4
121; CHECK-NEXT:    [[RESULT2:%.*]] = alloca i32, align 4
122; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
123; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
124; CHECK-NEXT:    br label [[BLOCK_2:%.*]]
125; CHECK:       block_1:
126; CHECK-NEXT:    [[A2:%.*]] = alloca i32, align 4
127; CHECK-NEXT:    [[B2:%.*]] = alloca i32, align 4
128; CHECK-NEXT:    br label [[BLOCK_2]]
129; CHECK:       block_2:
130; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[DIFF_CE_LOC]])
131; CHECK-NEXT:    call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[DIFF_CE_LOC]])
132; CHECK-NEXT:    [[DIFF_CE_RELOAD:%.*]] = load i32, ptr [[DIFF_CE_LOC]], align 4
133; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[DIFF_CE_LOC]])
134; CHECK-NEXT:    br label [[BLOCK_6:%.*]]
135; CHECK: dummy:
136; CHECK-NEXT:  ret void
137; CHECK:       block_6:
138; CHECK-NEXT:    [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ]
139; CHECK-NEXT:    ret void
140;
141;
142; CHECK:  define internal void @outlined_ir_func_0(
143; CHECK-NEXT:  newFuncRoot:
144; CHECK-NEXT:    br label [[BLOCK_2_TO_OUTLINE:%.*]]
145; CHECK:       block_2_to_outline:
146; CHECK-NEXT:    [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
147; CHECK-NEXT:    [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
148; CHECK-NEXT:    [[ADD2:%.*]] = add i32 2, [[A2VAL]]
149; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
150; CHECK-NEXT:    br label [[BLOCK_5:%.*]]
151; CHECK:       block_3:
152; CHECK-NEXT:    [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
153; CHECK-NEXT:    [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
154; CHECK-NEXT:    [[ADD:%.*]] = add i32 2, [[AVAL]]
155; CHECK-NEXT:    [[MUL:%.*]] = mul i32 2, [[BVAL]]
156; CHECK-NEXT:    br label [[BLOCK_4:%.*]]
157; CHECK:       block_4:
158; CHECK-NEXT:    store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
159; CHECK-NEXT:    store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
160; CHECK-NEXT:    br label [[BLOCK_6_SPLIT:%.*]]
161; CHECK:       block_5:
162; CHECK-NEXT:    store i32 [[ADD2]], ptr [[TMP2]], align 4
163; CHECK-NEXT:    store i32 [[MUL2]], ptr [[TMP3]], align 4
164; CHECK-NEXT:    br label [[BLOCK_6_SPLIT]]
165; CHECK:       block_6.split:
166; CHECK-NEXT:    [[DIFF_CE:%.*]] = phi i32 [ [[AVAL]], [[BLOCK_4]] ], [ [[A2VAL]], [[BLOCK_5]] ]
167; CHECK-NEXT:    br label [[BLOCK_6_EXITSTUB:%.*]]
168; CHECK:       block_6.exitStub:
169; CHECK-NEXT:    store i32 [[DIFF_CE]], ptr [[TMP4:%.*]], align 4
170; CHECK-NEXT:    ret void
171;
172