mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 10:56:07 +00:00

Refactor the pass to only support `IntrinsicInst` calls. `ReplaceWithVecLib` used to support instructions, as AArch64 was using this pass to replace a vectorized frem instruction to the fmod vector library call (through TLI). As this replacement is now done by the codegen (#83859), there is no need for this pass to support instructions. Additionally, removed 'frem' tests from: - AArch64/replace-with-veclib-armpl.ll - AArch64/replace-with-veclib-sleef-scalable.ll - AArch64/replace-with-veclib-sleef.ll Such testing is done at codegen level: - #83859
115 lines
4.1 KiB
C++
115 lines
4.1 KiB
C++
//===--- ReplaceWithVecLibTest.cpp - replace-with-veclib unit tests -------===//
|
|
//
|
|
// 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/CodeGen/ReplaceWithVeclib.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/AsmParser/Parser.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Passes/PassBuilder.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
/// NOTE: Assertions must be enabled for these tests to run.
|
|
#ifndef NDEBUG
|
|
|
|
namespace {
|
|
|
|
static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
|
|
SMDiagnostic Err;
|
|
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
|
|
if (!Mod)
|
|
Err.print("ReplaceWithVecLibTest", errs());
|
|
return Mod;
|
|
}
|
|
|
|
/// Runs ReplaceWithVecLib with different TLIIs that have custom VecDescs. This
|
|
/// allows checking that the pass won't crash when the function to replace (from
|
|
/// the input IR) does not match the replacement function (derived from the
|
|
/// VecDesc mapping).
|
|
///
|
|
class ReplaceWithVecLibTest : public ::testing::Test {
|
|
|
|
std::string getLastLine(std::string Out) {
|
|
// remove any trailing '\n'
|
|
if (!Out.empty() && *(Out.cend() - 1) == '\n')
|
|
Out.pop_back();
|
|
|
|
size_t LastNL = Out.find_last_of('\n');
|
|
return (LastNL == std::string::npos) ? Out : Out.substr(LastNL + 1);
|
|
}
|
|
|
|
protected:
|
|
LLVMContext Ctx;
|
|
|
|
/// Creates TLII using the given \p VD, and then runs the ReplaceWithVeclib
|
|
/// pass. The pass should not crash even when the replacement function
|
|
/// (derived from the \p VD mapping) does not match the function to be
|
|
/// replaced (from the input \p IR).
|
|
///
|
|
/// \returns the last line of the standard error to be compared for
|
|
/// correctness.
|
|
std::string run(const VecDesc &VD, const char *IR) {
|
|
// Create TLII and register it with FAM so it's preserved when
|
|
// ReplaceWithVeclib pass runs.
|
|
TargetLibraryInfoImpl TLII = TargetLibraryInfoImpl(Triple());
|
|
TLII.addVectorizableFunctions({VD});
|
|
FunctionAnalysisManager FAM;
|
|
FAM.registerPass([&TLII]() { return TargetLibraryAnalysis(TLII); });
|
|
|
|
// Register and run the pass on the 'foo' function from the input IR.
|
|
FunctionPassManager FPM;
|
|
FPM.addPass(ReplaceWithVeclib());
|
|
std::unique_ptr<Module> M = parseIR(Ctx, IR);
|
|
PassBuilder PB;
|
|
PB.registerFunctionAnalyses(FAM);
|
|
|
|
// Enable debugging and capture std error
|
|
bool DebugFlagPrev = llvm::DebugFlag;
|
|
llvm::DebugFlag = true;
|
|
testing::internal::CaptureStderr();
|
|
FPM.run(*M->getFunction("foo"), FAM);
|
|
llvm::DebugFlag = DebugFlagPrev;
|
|
return getLastLine(testing::internal::GetCapturedStderr());
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
static const char *IR = R"IR(
|
|
define <vscale x 4 x float> @foo(<vscale x 4 x float> %in){
|
|
%call = call <vscale x 4 x float> @llvm.powi.f32.i32(<vscale x 4 x float> %in, i32 3)
|
|
ret <vscale x 4 x float> %call
|
|
}
|
|
|
|
declare <vscale x 4 x float> @llvm.powi.f32.i32(<vscale x 4 x float>, i32) #0
|
|
)IR";
|
|
|
|
// The VFABI prefix in TLI describes signature which is matching the powi
|
|
// intrinsic declaration.
|
|
TEST_F(ReplaceWithVecLibTest, TestValidMapping) {
|
|
VecDesc CorrectVD = {"llvm.powi.f32.i32", "_ZGVsMxvu_powi",
|
|
ElementCount::getScalable(4), /*Masked*/ true,
|
|
"_ZGVsMxvu"};
|
|
EXPECT_EQ(run(CorrectVD, IR),
|
|
"Intrinsic calls replaced with vector libraries: 1");
|
|
}
|
|
|
|
// The VFABI prefix in TLI describes signature which is not matching the powi
|
|
// intrinsic declaration.
|
|
TEST_F(ReplaceWithVecLibTest, TestInvalidMapping) {
|
|
VecDesc IncorrectVD = {"llvm.powi.f32.i32", "_ZGVsMxvv_powi",
|
|
ElementCount::getScalable(4), /*Masked*/ true,
|
|
"_ZGVsMxvv"};
|
|
EXPECT_EQ(run(IncorrectVD, IR),
|
|
"replace-with-veclib: Will not replace: llvm.powi.f32.i32. Wrong "
|
|
"type at index 1: i32");
|
|
}
|
|
#endif |