xref: /llvm-project/llvm/test/Transforms/IROutliner/outlining-multiple-exits-one-output-set.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 different sources, and only one has an
5; output set.  We check to make sure that we do not generated extra output
6; blocks or entries in the switch statement.
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_7
41block_6:
42  ret void
43block_7:
44  ret void
45}
46
47define void @outline_outputs2() #0 {
48entry:
49  %output = alloca i32, align 4
50  %result = alloca i32, align 4
51  %output2 = alloca i32, align 4
52  %result2 = alloca i32, align 4
53  %a = alloca i32, align 4
54  %b = alloca i32, align 4
55  br label %block_2
56block_1:
57  %a2 = alloca i32, align 4
58  %b2 = alloca i32, align 4
59  br label %block_2
60block_2:
61  %a2val = load i32, ptr %a
62  %b2val = load i32, ptr %b
63  %add2 = add i32 2, %a2val
64  %mul2 = mul i32 2, %b2val
65  br label %block_5
66block_3:
67  %aval = load i32, ptr %a
68  %bval = load i32, ptr %b
69  %add = add i32 2, %aval
70  %mul = mul i32 2, %bval
71  br label %block_4
72block_4:
73  store i32 %add, ptr %output, align 4
74  store i32 %mul, ptr %result, align 4
75  br label %block_7
76block_5:
77  store i32 %add2, ptr %output, align 4
78  store i32 %mul2, ptr %result, align 4
79  br label %block_6
80block_6:
81  %diff = sub i32 %a2val, %b2val
82  ret void
83block_7:
84  %quot = udiv i32 %add, %mul
85  ret void
86}
87; CHECK-LABEL: @outline_outputs1(
88; CHECK-NEXT:  entry:
89; CHECK-NEXT:    [[OUTPUT:%.*]] = alloca i32, align 4
90; CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
91; CHECK-NEXT:    [[OUTPUT2:%.*]] = alloca i32, align 4
92; CHECK-NEXT:    [[RESULT2:%.*]] = alloca i32, align 4
93; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
94; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
95; CHECK-NEXT:    br label [[BLOCK_2:%.*]]
96; CHECK:       block_1:
97; CHECK-NEXT:    [[A2:%.*]] = alloca i32, align 4
98; CHECK-NEXT:    [[B2:%.*]] = alloca i32, align 4
99; CHECK-NEXT:    br label [[BLOCK_2]]
100; CHECK:       block_2:
101; CHECK-NEXT:    [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr null, ptr null, ptr null, ptr null, i32 -1)
102; CHECK-NEXT:    br i1 [[TMP0]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
103; CHECK:       block_6:
104; CHECK-NEXT:    ret void
105; CHECK:       block_7:
106; CHECK-NEXT:    ret void
107;
108;
109; CHECK-LABEL: @outline_outputs2(
110; CHECK-NEXT:  entry:
111; CHECK-NEXT:    [[MUL_LOC:%.*]] = alloca i32, align 4
112; CHECK-NEXT:    [[ADD_LOC:%.*]] = alloca i32, align 4
113; CHECK-NEXT:    [[B2VAL_LOC:%.*]] = alloca i32, align 4
114; CHECK-NEXT:    [[A2VAL_LOC:%.*]] = alloca i32, align 4
115; CHECK-NEXT:    [[OUTPUT:%.*]] = alloca i32, align 4
116; CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
117; CHECK-NEXT:    [[OUTPUT2:%.*]] = alloca i32, align 4
118; CHECK-NEXT:    [[RESULT2:%.*]] = alloca i32, align 4
119; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
120; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
121; CHECK-NEXT:    br label [[BLOCK_2:%.*]]
122; CHECK:       block_1:
123; CHECK-NEXT:    [[A2:%.*]] = alloca i32, align 4
124; CHECK-NEXT:    [[B2:%.*]] = alloca i32, align 4
125; CHECK-NEXT:    br label [[BLOCK_2]]
126; CHECK:       block_2:
127; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[A2VAL_LOC]])
128; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[B2VAL_LOC]])
129; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[ADD_LOC]])
130; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr [[MUL_LOC]])
131; CHECK-NEXT:    [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[ADD_LOC]], ptr [[MUL_LOC]], i32 0)
132; CHECK-NEXT:    [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
133; CHECK-NEXT:    [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
134; CHECK-NEXT:    [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
135; CHECK-NEXT:    [[MUL_RELOAD:%.*]] = load i32, ptr [[MUL_LOC]], align 4
136; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[A2VAL_LOC]])
137; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[B2VAL_LOC]])
138; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[ADD_LOC]])
139; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr [[MUL_LOC]])
140; CHECK-NEXT:    br i1 [[TMP0]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
141; CHECK:       block_6:
142; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
143; CHECK-NEXT:    ret void
144; CHECK:       block_7:
145; CHECK-NEXT:    [[QUOT:%.*]] = udiv i32 [[ADD_RELOAD]], [[MUL_RELOAD]]
146; CHECK-NEXT:    ret void
147;
148;
149; CHECK: define internal i1 @outlined_ir_func_0(
150; CHECK-NEXT:  newFuncRoot:
151; CHECK-NEXT:    br label [[BLOCK_2_TO_OUTLINE:%.*]]
152; CHECK:       block_2_to_outline:
153; CHECK-NEXT:    [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
154; CHECK-NEXT:    [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
155; CHECK-NEXT:    [[ADD2:%.*]] = add i32 2, [[A2VAL]]
156; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
157; CHECK-NEXT:    br label [[BLOCK_5:%.*]]
158; CHECK:       block_3:
159; CHECK-NEXT:    [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
160; CHECK-NEXT:    [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
161; CHECK-NEXT:    [[ADD:%.*]] = add i32 2, [[AVAL]]
162; CHECK-NEXT:    [[MUL:%.*]] = mul i32 2, [[BVAL]]
163; CHECK-NEXT:    br label [[BLOCK_4:%.*]]
164; CHECK:       block_4:
165; CHECK-NEXT:    store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
166; CHECK-NEXT:    store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
167; CHECK-NEXT:    br label [[BLOCK_6_EXITSTUB:%.*]]
168; CHECK:       block_5:
169; CHECK-NEXT:    store i32 [[ADD2]], ptr [[TMP2]], align 4
170; CHECK-NEXT:    store i32 [[MUL2]], ptr [[TMP3]], align 4
171; CHECK-NEXT:    br label [[BLOCK_7_EXITSTUB:%.*]]
172; CHECK:       block_6.exitStub:
173; CHECK-NEXT:    switch i32 [[TMP8:%.*]], label [[FINAL_BLOCK_1:%.*]] [
174; CHECK-NEXT:    i32 0, label [[OUTPUT_BLOCK_1_1:%.*]]
175; CHECK-NEXT:    ]
176; CHECK:       block_7.exitStub:
177; CHECK-NEXT:    switch i32 [[TMP8]], label [[FINAL_BLOCK_0:%.*]] [
178; CHECK-NEXT:    i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
179; CHECK-NEXT:    ]
180; CHECK:       output_block_1_0:
181; CHECK-NEXT:    store i32 [[A2VAL]], ptr [[TMP4:%.*]], align 4
182; CHECK-NEXT:    store i32 [[B2VAL]], ptr [[TMP5:%.*]], align 4
183; CHECK-NEXT:    br label [[FINAL_BLOCK_0]]
184; CHECK:       output_block_1_1:
185; CHECK-NEXT:    store i32 [[ADD]], ptr [[TMP6:%.*]], align 4
186; CHECK-NEXT:    store i32 [[MUL]], ptr [[TMP7:%.*]], align 4
187; CHECK-NEXT:    br label [[FINAL_BLOCK_1]]
188; CHECK:       final_block_0:
189; CHECK-NEXT:    ret i1 false
190; CHECK:       final_block_1:
191; CHECK-NEXT:    ret i1 true
192;
193