[OptTable] Fix typo VALUE => VALUES (NFCI) (#121523)
[llvm-project.git] / llvm / unittests / Transforms / IPO / MergeFunctionsTest.cpp
blob56d119878a9ab24670b983bd1c2d889b4f412527
1 //===- MergeFunctionsTest.cpp - Unit tests for MergeFunctionsPass ---------===//
2 //
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
6 //
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"
17 #include <memory>
19 using namespace llvm;
21 namespace {
23 TEST(MergeFunctions, TrueOutputModuleTest) {
24 LLVMContext Ctx;
25 SMDiagnostic Err;
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) {
31 entry:
32 %add109 = call i32 @_slice_add10(i32 %arg)
33 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
34 ret i32 %add109
37 declare i32 @printf(ptr noundef, ...)
39 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
40 entry:
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)
45 ret i32 %add99
48 define internal i32 @_slice_add10(i32 %arg) {
49 sliceclone_entry:
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
55 ret i32 %4
58 define internal i32 @_slice_add10_alt(i32 %arg) {
59 sliceclone_entry:
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
65 ret i32 %4
67 )invalid",
68 Err, Ctx));
70 // Expects true after merging _slice_add10 and _slice_add10_alt
71 EXPECT_TRUE(MergeFunctionsPass::runOnModule(*M));
74 TEST(MergeFunctions, TrueOutputFunctionsTest) {
75 LLVMContext Ctx;
76 SMDiagnostic Err;
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) {
82 entry:
83 %add109 = call i32 @_slice_add10(i32 %arg)
84 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
85 ret i32 %add109
88 declare i32 @printf(ptr noundef, ...)
90 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
91 entry:
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)
96 ret i32 %add99
99 define internal i32 @_slice_add10(i32 %arg) {
100 sliceclone_entry:
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
106 ret i32 %4
109 define internal i32 @_slice_add10_alt(i32 %arg) {
110 sliceclone_entry:
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
116 ret i32 %4
118 )invalid",
119 Err, Ctx));
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)
133 if (P.second)
134 EXPECT_EQ(P.second, NewFunction);
137 TEST(MergeFunctions, FalseOutputModuleTest) {
138 LLVMContext Ctx;
139 SMDiagnostic Err;
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) {
145 entry:
146 %add109 = call i32 @_slice_add10(i32 %arg)
147 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
148 ret i32 %add109
151 declare i32 @printf(ptr noundef, ...)
153 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
154 entry:
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)
159 ret i32 %add99
162 define internal i32 @_slice_add10(i32 %arg) {
163 sliceclone_entry:
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
169 ret i32 %4
172 define internal i32 @_slice_add10_alt(i32 %arg) {
173 sliceclone_entry:
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
179 ret i32 %0
181 )invalid",
182 Err, Ctx));
184 // Expects false after trying to merge _slice_add10 and _slice_add10_alt
185 EXPECT_FALSE(MergeFunctionsPass::runOnModule(*M));
188 TEST(MergeFunctions, FalseOutputFunctionsTest) {
189 LLVMContext Ctx;
190 SMDiagnostic Err;
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) {
196 entry:
197 %add109 = call i32 @_slice_add10(i32 %arg)
198 %call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
199 ret i32 %add109
202 declare i32 @printf(ptr noundef, ...)
204 define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
205 entry:
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)
210 ret i32 %add99
213 define internal i32 @_slice_add10(i32 %arg) {
214 sliceclone_entry:
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
220 ret i32 %4
223 define internal i32 @_slice_add10_alt(i32 %arg) {
224 sliceclone_entry:
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
230 ret i32 %0
232 )invalid",
233 Err, Ctx));
235 SetVector<Function *> FunctionsSet;
236 for (Function &F : *M)
237 FunctionsSet.insert(&F);
239 DenseMap<Function *, Function *> MergeResult =
240 MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef());
242 // Expects empty map
243 EXPECT_EQ(MergeResult.size(), 0u);
246 } // namespace