
This avoids the need to dynamically relocate each pointer in the table. To make this work, this PR also moves the binary search of intrinsic names to an internal function with an adjusted signature, and switches the unittesting to test against actual intrinsics.
167 lines
6.5 KiB
C++
167 lines
6.5 KiB
C++
//===- llvm/unittest/IR/IntrinsicsTest.cpp - ------------------------------===//
|
|
//
|
|
// 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/IR/Intrinsics.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/IR/Constant.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/IntrinsicsAArch64.h"
|
|
#include "llvm/IR/IntrinsicsAMDGPU.h"
|
|
#include "llvm/IR/IntrinsicsARM.h"
|
|
#include "llvm/IR/IntrinsicsBPF.h"
|
|
#include "llvm/IR/IntrinsicsDirectX.h"
|
|
#include "llvm/IR/IntrinsicsHexagon.h"
|
|
#include "llvm/IR/IntrinsicsLoongArch.h"
|
|
#include "llvm/IR/IntrinsicsMips.h"
|
|
#include "llvm/IR/IntrinsicsNVPTX.h"
|
|
#include "llvm/IR/IntrinsicsPowerPC.h"
|
|
#include "llvm/IR/IntrinsicsRISCV.h"
|
|
#include "llvm/IR/IntrinsicsS390.h"
|
|
#include "llvm/IR/IntrinsicsX86.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class IntrinsicsTest : public ::testing::Test {
|
|
LLVMContext Context;
|
|
std::unique_ptr<Module> M;
|
|
BasicBlock *BB = nullptr;
|
|
|
|
void TearDown() override { M.reset(); }
|
|
|
|
void SetUp() override {
|
|
M = std::make_unique<Module>("Test", Context);
|
|
auto F = M->getOrInsertFunction(
|
|
"test", FunctionType::get(Type::getVoidTy(Context), false));
|
|
BB = BasicBlock::Create(Context, "", cast<Function>(F.getCallee()));
|
|
EXPECT_NE(BB, nullptr);
|
|
}
|
|
|
|
public:
|
|
Instruction *makeIntrinsic(Intrinsic::ID ID) const {
|
|
IRBuilder<> Builder(BB);
|
|
SmallVector<Value *, 4> ProcessedArgs;
|
|
auto *Decl = Intrinsic::getOrInsertDeclaration(M.get(), ID);
|
|
for (auto *Ty : Decl->getFunctionType()->params()) {
|
|
auto *Val = Constant::getNullValue(Ty);
|
|
ProcessedArgs.push_back(Val);
|
|
}
|
|
return Builder.CreateCall(Decl, ProcessedArgs);
|
|
}
|
|
template <typename T> void checkIsa(const Instruction &I) {
|
|
EXPECT_TRUE(isa<T>(I));
|
|
}
|
|
};
|
|
|
|
TEST(IntrinsicNameLookup, Basic) {
|
|
using namespace Intrinsic;
|
|
EXPECT_EQ(Intrinsic::memcpy, lookupIntrinsicID("llvm.memcpy"));
|
|
|
|
// Partial, either between dots or not the last dot are not intrinsics.
|
|
EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.mem"));
|
|
EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.gc"));
|
|
|
|
// Look through intrinsic names with internal dots.
|
|
EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline"));
|
|
|
|
// Check that overloaded names are mapped to the underlying ID.
|
|
EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i8"));
|
|
EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i32"));
|
|
EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i64"));
|
|
EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i1024"));
|
|
}
|
|
|
|
// Tests to verify getIntrinsicForClangBuiltin.
|
|
TEST(IntrinsicNameLookup, ClangBuiltinLookup) {
|
|
using namespace Intrinsic;
|
|
static constexpr std::tuple<StringRef, StringRef, ID> ClangTests[] = {
|
|
{"__builtin_adjust_trampoline", "", adjust_trampoline},
|
|
{"__builtin_trap", "", trap},
|
|
{"__builtin_arm_chkfeat", "aarch64", aarch64_chkfeat},
|
|
{"__builtin_amdgcn_alignbyte", "amdgcn", amdgcn_alignbyte},
|
|
{"__builtin_amdgcn_workgroup_id_z", "amdgcn", amdgcn_workgroup_id_z},
|
|
{"__builtin_arm_cdp", "arm", arm_cdp},
|
|
{"__builtin_bpf_preserve_type_info", "bpf", bpf_preserve_type_info},
|
|
{"__builtin_HEXAGON_A2_tfr", "hexagon", hexagon_A2_tfr},
|
|
{"__builtin_lasx_xbz_w", "loongarch", loongarch_lasx_xbz_w},
|
|
{"__builtin_mips_bitrev", "mips", mips_bitrev},
|
|
{"__nvvm_add_rn_d", "nvvm", nvvm_add_rn_d},
|
|
{"__builtin_altivec_dss", "ppc", ppc_altivec_dss},
|
|
{"__builtin_riscv_sha512sum1r", "riscv", riscv_sha512sum1r},
|
|
{"__builtin_tend", "s390", s390_tend},
|
|
{"__builtin_ia32_pause", "x86", x86_sse2_pause},
|
|
|
|
{"__does_not_exist", "", not_intrinsic},
|
|
{"__does_not_exist", "arm", not_intrinsic},
|
|
{"__builtin_arm_cdp", "", not_intrinsic},
|
|
{"__builtin_arm_cdp", "x86", not_intrinsic},
|
|
};
|
|
|
|
for (const auto &[Builtin, Target, ID] : ClangTests)
|
|
EXPECT_EQ(ID, getIntrinsicForClangBuiltin(Target, Builtin));
|
|
}
|
|
|
|
// Tests to verify getIntrinsicForMSBuiltin.
|
|
TEST(IntrinsicNameLookup, MSBuiltinLookup) {
|
|
using namespace Intrinsic;
|
|
static constexpr std::tuple<StringRef, StringRef, ID> MSTests[] = {
|
|
{"__dmb", "aarch64", aarch64_dmb},
|
|
{"__dmb", "arm", arm_dmb},
|
|
{"__dmb", "", not_intrinsic},
|
|
{"__does_not_exist", "", not_intrinsic},
|
|
{"__does_not_exist", "arm", not_intrinsic},
|
|
};
|
|
for (const auto &[Builtin, Target, ID] : MSTests)
|
|
EXPECT_EQ(ID, getIntrinsicForMSBuiltin(Target, Builtin));
|
|
}
|
|
|
|
TEST_F(IntrinsicsTest, InstrProfInheritance) {
|
|
auto isInstrProfInstBase = [](const Instruction &I) {
|
|
return isa<InstrProfInstBase>(I);
|
|
};
|
|
#define __ISA(TYPE, PARENT) \
|
|
auto is##TYPE = [&](const Instruction &I) -> bool { \
|
|
return isa<TYPE>(I) && is##PARENT(I); \
|
|
}
|
|
__ISA(InstrProfCntrInstBase, InstrProfInstBase);
|
|
__ISA(InstrProfCoverInst, InstrProfCntrInstBase);
|
|
__ISA(InstrProfIncrementInst, InstrProfCntrInstBase);
|
|
__ISA(InstrProfIncrementInstStep, InstrProfIncrementInst);
|
|
__ISA(InstrProfCallsite, InstrProfCntrInstBase);
|
|
__ISA(InstrProfTimestampInst, InstrProfCntrInstBase);
|
|
__ISA(InstrProfValueProfileInst, InstrProfCntrInstBase);
|
|
__ISA(InstrProfMCDCBitmapInstBase, InstrProfInstBase);
|
|
__ISA(InstrProfMCDCBitmapParameters, InstrProfMCDCBitmapInstBase);
|
|
__ISA(InstrProfMCDCTVBitmapUpdate, InstrProfMCDCBitmapInstBase);
|
|
#undef __ISA
|
|
|
|
std::vector<
|
|
std::pair<Intrinsic::ID, std::function<bool(const Instruction &)>>>
|
|
LeafIDs = {
|
|
{Intrinsic::instrprof_cover, isInstrProfCoverInst},
|
|
{Intrinsic::instrprof_increment, isInstrProfIncrementInst},
|
|
{Intrinsic::instrprof_increment_step, isInstrProfIncrementInstStep},
|
|
{Intrinsic::instrprof_callsite, isInstrProfCallsite},
|
|
{Intrinsic::instrprof_mcdc_parameters,
|
|
isInstrProfMCDCBitmapParameters},
|
|
{Intrinsic::instrprof_mcdc_tvbitmap_update,
|
|
isInstrProfMCDCTVBitmapUpdate},
|
|
{Intrinsic::instrprof_timestamp, isInstrProfTimestampInst},
|
|
{Intrinsic::instrprof_value_profile, isInstrProfValueProfileInst}};
|
|
for (const auto &[ID, Checker] : LeafIDs) {
|
|
auto *Intr = makeIntrinsic(ID);
|
|
EXPECT_TRUE(Checker(*Intr));
|
|
}
|
|
}
|
|
|
|
} // end namespace
|