llvm-project/llvm/unittests/Transforms/IPO/MergeFunctionsTest.cpp
Nikita Popov b96e7570c9 [UnitTests] Move MergeFunction test from Utils to IPO
So we depend on the correct library.
2024-11-28 16:25:05 +01:00

246 lines
8.5 KiB
C++

//===- MergeFunctionsTest.cpp - Unit tests for MergeFunctionsPass ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/MergeFunctions.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
#include <memory>
using namespace llvm;
namespace {
TEST(MergeFunctions, TrueOutputModuleTest) {
LLVMContext Ctx;
SMDiagnostic Err;
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
@.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", align 1
@.str.1 = private unnamed_addr constant [13 x i8] c"On main: %d\0A\00", align 1
define dso_local i32 @f(i32 noundef %arg) {
entry:
%add109 = call i32 @_slice_add10(i32 %arg)
%call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
ret i32 %add109
}
declare i32 @printf(ptr noundef, ...)
define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
entry:
%add99 = call i32 @_slice_add10(i32 %argc)
%call = call i32 @f(i32 noundef 2)
%sub = sub nsw i32 %call, 6
%call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
ret i32 %add99
}
define internal i32 @_slice_add10(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
define internal i32 @_slice_add10_alt(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
)invalid",
Err, Ctx));
// Expects true after merging _slice_add10 and _slice_add10_alt
EXPECT_TRUE(MergeFunctionsPass::runOnModule(*M));
}
TEST(MergeFunctions, TrueOutputFunctionsTest) {
LLVMContext Ctx;
SMDiagnostic Err;
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
@.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", align 1
@.str.1 = private unnamed_addr constant [13 x i8] c"On main: %d\0A\00", align 1
define dso_local i32 @f(i32 noundef %arg) {
entry:
%add109 = call i32 @_slice_add10(i32 %arg)
%call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
ret i32 %add109
}
declare i32 @printf(ptr noundef, ...)
define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
entry:
%add99 = call i32 @_slice_add10(i32 %argc)
%call = call i32 @f(i32 noundef 2)
%sub = sub nsw i32 %call, 6
%call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
ret i32 %add99
}
define internal i32 @_slice_add10(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
define internal i32 @_slice_add10_alt(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
)invalid",
Err, Ctx));
SetVector<Function *> FunctionsSet;
for (Function &F : *M)
FunctionsSet.insert(&F);
DenseMap<Function *, Function *> MergeResult =
MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef());
// Expects that both functions (_slice_add10 and _slice_add10_alt)
// be mapped to the same new function
EXPECT_TRUE(!MergeResult.empty());
Function *NewFunction = M->getFunction("_slice_add10");
for (auto P : MergeResult)
if (P.second)
EXPECT_EQ(P.second, NewFunction);
}
TEST(MergeFunctions, FalseOutputModuleTest) {
LLVMContext Ctx;
SMDiagnostic Err;
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
@.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", align 1
@.str.1 = private unnamed_addr constant [13 x i8] c"On main: %d\0A\00", align 1
define dso_local i32 @f(i32 noundef %arg) {
entry:
%add109 = call i32 @_slice_add10(i32 %arg)
%call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
ret i32 %add109
}
declare i32 @printf(ptr noundef, ...)
define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
entry:
%add99 = call i32 @_slice_add10(i32 %argc)
%call = call i32 @f(i32 noundef 2)
%sub = sub nsw i32 %call, 6
%call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
ret i32 %add99
}
define internal i32 @_slice_add10(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
define internal i32 @_slice_add10_alt(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %0
}
)invalid",
Err, Ctx));
// Expects false after trying to merge _slice_add10 and _slice_add10_alt
EXPECT_FALSE(MergeFunctionsPass::runOnModule(*M));
}
TEST(MergeFunctions, FalseOutputFunctionsTest) {
LLVMContext Ctx;
SMDiagnostic Err;
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
@.str = private unnamed_addr constant [10 x i8] c"On f: %d\0A\00", align 1
@.str.1 = private unnamed_addr constant [13 x i8] c"On main: %d\0A\00", align 1
define dso_local i32 @f(i32 noundef %arg) {
entry:
%add109 = call i32 @_slice_add10(i32 %arg)
%call = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %add109)
ret i32 %add109
}
declare i32 @printf(ptr noundef, ...)
define dso_local i32 @main(i32 noundef %argc, ptr noundef %argv) {
entry:
%add99 = call i32 @_slice_add10(i32 %argc)
%call = call i32 @f(i32 noundef 2)
%sub = sub nsw i32 %call, 6
%call10 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %add99)
ret i32 %add99
}
define internal i32 @_slice_add10(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %4
}
define internal i32 @_slice_add10_alt(i32 %arg) {
sliceclone_entry:
%0 = mul nsw i32 %arg, %arg
%1 = mul nsw i32 %0, 2
%2 = mul nsw i32 %1, 2
%3 = mul nsw i32 %2, 2
%4 = add nsw i32 %3, 2
ret i32 %0
}
)invalid",
Err, Ctx));
SetVector<Function *> FunctionsSet;
for (Function &F : *M)
FunctionsSet.insert(&F);
DenseMap<Function *, Function *> MergeResult =
MergeFunctionsPass::runOnFunctions(FunctionsSet.getArrayRef());
// Expects empty map
EXPECT_EQ(MergeResult.size(), 0u);
}
} // namespace