1 //===- MergeFunctionsTest.cpp - Unit tests for MergeFunctionsPass ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/IPO/MergeFunctions.h"
11 #include "llvm/ADT/SetVector.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
23 TEST(MergeFunctions
, TrueOutputModuleTest
) {
26 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
27 @.str = private unnamed_addr constant [10 x i8] c"On f
: %d\
0A\
00", align 1
28 @.str.1 = private unnamed_addr constant [13 x i8] c"On main
: %d\
0A\
00", align 1
30 define dso_local i32 @f(i32 noundef %arg) {
32 %add109 = call i32 @_slice_add10(i32 %arg)
33 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
37 declare i32 @printf(ptr noundef, ...)
39 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
41 %add99 = call i32 @_slice_add10(i32 %argc)
42 %call = call i32 @f(i32 noundef 2)
43 %sub = sub nsw i32 %call, 6
44 %call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
48 define internal i32 @_slice_add10(i32 %arg) {
50 %0 = mul nsw i32 %arg, %arg
51 %1 = mul nsw i32 %0, 2
52 %2 = mul nsw i32 %1, 2
53 %3 = mul nsw i32 %2, 2
54 %4 = add nsw i32 %3, 2
58 define internal i32 @_slice_add10_alt(i32 %arg) {
60 %0 = mul nsw i32 %arg, %arg
61 %1 = mul nsw i32 %0, 2
62 %2 = mul nsw i32 %1, 2
63 %3 = mul nsw i32 %2, 2
64 %4 = add nsw i32 %3, 2
70 // Expects true after merging _slice_add10 and _slice_add10_alt
71 EXPECT_TRUE(MergeFunctionsPass::runOnModule(*M
));
74 TEST(MergeFunctions
, TrueOutputFunctionsTest
) {
77 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
78 @.str = private unnamed_addr constant [10 x i8] c"On f
: %d\
0A\
00", align 1
79 @.str.1 = private unnamed_addr constant [13 x i8] c"On main
: %d\
0A\
00", align 1
81 define dso_local i32 @f(i32 noundef %arg) {
83 %add109 = call i32 @_slice_add10(i32 %arg)
84 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
88 declare i32 @printf(ptr noundef, ...)
90 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
92 %add99 = call i32 @_slice_add10(i32 %argc)
93 %call = call i32 @f(i32 noundef 2)
94 %sub = sub nsw i32 %call, 6
95 %call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
99 define internal i32 @_slice_add10(i32 %arg) {
101 %0 = mul nsw i32 %arg, %arg
102 %1 = mul nsw i32 %0, 2
103 %2 = mul nsw i32 %1, 2
104 %3 = mul nsw i32 %2, 2
105 %4 = add nsw i32 %3, 2
109 define internal i32 @_slice_add10_alt(i32 %arg) {
111 %0 = mul nsw i32 %arg, %arg
112 %1 = mul nsw i32 %0, 2
113 %2 = mul nsw i32 %1, 2
114 %3 = mul nsw i32 %2, 2
115 %4 = add nsw i32 %3, 2
121 SetVector
<Function
*> FunctionsSet
;
122 for (Function
&F
: *M
)
123 FunctionsSet
.insert(&F
);
125 DenseMap
<Function
*, Function
*> MergeResult
=
126 MergeFunctionsPass::runOnFunctions(FunctionsSet
.getArrayRef());
128 // Expects that both functions (_slice_add10 and _slice_add10_alt)
129 // be mapped to the same new function
130 EXPECT_TRUE(!MergeResult
.empty());
131 Function
*NewFunction
= M
->getFunction("_slice_add10");
132 for (auto P
: MergeResult
)
134 EXPECT_EQ(P
.second
, NewFunction
);
137 TEST(MergeFunctions
, FalseOutputModuleTest
) {
140 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
141 @.str = private unnamed_addr constant [10 x i8] c"On f
: %d\
0A\
00", align 1
142 @.str.1 = private unnamed_addr constant [13 x i8] c"On main
: %d\
0A\
00", align 1
144 define dso_local i32 @f(i32 noundef %arg) {
146 %add109 = call i32 @_slice_add10(i32 %arg)
147 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
151 declare i32 @printf(ptr noundef, ...)
153 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
155 %add99 = call i32 @_slice_add10(i32 %argc)
156 %call = call i32 @f(i32 noundef 2)
157 %sub = sub nsw i32 %call, 6
158 %call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
162 define internal i32 @_slice_add10(i32 %arg) {
164 %0 = mul nsw i32 %arg, %arg
165 %1 = mul nsw i32 %0, 2
166 %2 = mul nsw i32 %1, 2
167 %3 = mul nsw i32 %2, 2
168 %4 = add nsw i32 %3, 2
172 define internal i32 @_slice_add10_alt(i32 %arg) {
174 %0 = mul nsw i32 %arg, %arg
175 %1 = mul nsw i32 %0, 2
176 %2 = mul nsw i32 %1, 2
177 %3 = mul nsw i32 %2, 2
178 %4 = add nsw i32 %3, 2
184 // Expects false after trying to merge _slice_add10 and _slice_add10_alt
185 EXPECT_FALSE(MergeFunctionsPass::runOnModule(*M
));
188 TEST(MergeFunctions
, FalseOutputFunctionsTest
) {
191 std::unique_ptr
<Module
> M(parseAssemblyString(R
"invalid(
192 @.str = private unnamed_addr constant [10 x i8] c"On f
: %d\
0A\
00", align 1
193 @.str.1 = private unnamed_addr constant [13 x i8] c"On main
: %d\
0A\
00", align 1
195 define dso_local i32 @f(i32 noundef %arg) {
197 %add109 = call i32 @_slice_add10(i32 %arg)
198 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
202 declare i32 @printf(ptr noundef, ...)
204 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
206 %add99 = call i32 @_slice_add10(i32 %argc)
207 %call = call i32 @f(i32 noundef 2)
208 %sub = sub nsw i32 %call, 6
209 %call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
213 define internal i32 @_slice_add10(i32 %arg) {
215 %0 = mul nsw i32 %arg, %arg
216 %1 = mul nsw i32 %0, 2
217 %2 = mul nsw i32 %1, 2
218 %3 = mul nsw i32 %2, 2
219 %4 = add nsw i32 %3, 2
223 define internal i32 @_slice_add10_alt(i32 %arg) {
225 %0 = mul nsw i32 %arg, %arg
226 %1 = mul nsw i32 %0, 2
227 %2 = mul nsw i32 %1, 2
228 %3 = mul nsw i32 %2, 2
229 %4 = add nsw i32 %3, 2
235 SetVector
<Function
*> FunctionsSet
;
236 for (Function
&F
: *M
)
237 FunctionsSet
.insert(&F
);
239 DenseMap
<Function
*, Function
*> MergeResult
=
240 MergeFunctionsPass::runOnFunctions(FunctionsSet
.getArrayRef());
243 EXPECT_EQ(MergeResult
.size(), 0u);