xref: /llvm-project/llvm/unittests/IR/IntrinsicsTest.cpp (revision f0297ae552e1e5aacafc1ed43968041994dc8a6e)
1 //===- llvm/unittest/IR/IntrinsicsTest.cpp - ------------------------------===//
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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/IR/Intrinsics.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/IR/Constant.h"
12 #include "llvm/IR/IRBuilder.h"
13 #include "llvm/IR/IntrinsicInst.h"
14 #include "llvm/IR/IntrinsicsAArch64.h"
15 #include "llvm/IR/IntrinsicsAMDGPU.h"
16 #include "llvm/IR/IntrinsicsARM.h"
17 #include "llvm/IR/IntrinsicsBPF.h"
18 #include "llvm/IR/IntrinsicsDirectX.h"
19 #include "llvm/IR/IntrinsicsHexagon.h"
20 #include "llvm/IR/IntrinsicsLoongArch.h"
21 #include "llvm/IR/IntrinsicsMips.h"
22 #include "llvm/IR/IntrinsicsNVPTX.h"
23 #include "llvm/IR/IntrinsicsPowerPC.h"
24 #include "llvm/IR/IntrinsicsRISCV.h"
25 #include "llvm/IR/IntrinsicsS390.h"
26 #include "llvm/IR/IntrinsicsX86.h"
27 #include "llvm/IR/Module.h"
28 #include "gtest/gtest.h"
29 
30 using namespace llvm;
31 
32 namespace {
33 
34 class IntrinsicsTest : public ::testing::Test {
35   LLVMContext Context;
36   std::unique_ptr<Module> M;
37   BasicBlock *BB = nullptr;
38 
39   void TearDown() override { M.reset(); }
40 
41   void SetUp() override {
42     M = std::make_unique<Module>("Test", Context);
43     auto F = M->getOrInsertFunction(
44         "test", FunctionType::get(Type::getVoidTy(Context), false));
45     BB = BasicBlock::Create(Context, "", cast<Function>(F.getCallee()));
46     EXPECT_NE(BB, nullptr);
47   }
48 
49 public:
50   Instruction *makeIntrinsic(Intrinsic::ID ID) const {
51     IRBuilder<> Builder(BB);
52     SmallVector<Value *, 4> ProcessedArgs;
53     auto *Decl = Intrinsic::getOrInsertDeclaration(M.get(), ID);
54     for (auto *Ty : Decl->getFunctionType()->params()) {
55       auto *Val = Constant::getNullValue(Ty);
56       ProcessedArgs.push_back(Val);
57     }
58     return Builder.CreateCall(Decl, ProcessedArgs);
59   }
60   template <typename T> void checkIsa(const Instruction &I) {
61     EXPECT_TRUE(isa<T>(I));
62   }
63 };
64 
65 TEST(IntrinsicNameLookup, Basic) {
66   using namespace Intrinsic;
67   EXPECT_EQ(Intrinsic::memcpy, lookupIntrinsicID("llvm.memcpy"));
68 
69   // Partial, either between dots or not the last dot are not intrinsics.
70   EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.mem"));
71   EXPECT_EQ(not_intrinsic, lookupIntrinsicID("llvm.gc"));
72 
73   // Look through intrinsic names with internal dots.
74   EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline"));
75 
76   // Check that overloaded names are mapped to the underlying ID.
77   EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i8"));
78   EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i32"));
79   EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i64"));
80   EXPECT_EQ(memcpy_inline, lookupIntrinsicID("llvm.memcpy.inline.p0.p0.i1024"));
81 }
82 
83 // Tests to verify getIntrinsicForClangBuiltin.
84 TEST(IntrinsicNameLookup, ClangBuiltinLookup) {
85   using namespace Intrinsic;
86   static constexpr std::tuple<StringRef, StringRef, ID> ClangTests[] = {
87       {"__builtin_adjust_trampoline", "", adjust_trampoline},
88       {"__builtin_trap", "", trap},
89       {"__builtin_arm_chkfeat", "aarch64", aarch64_chkfeat},
90       {"__builtin_amdgcn_alignbyte", "amdgcn", amdgcn_alignbyte},
91       {"__builtin_amdgcn_workgroup_id_z", "amdgcn", amdgcn_workgroup_id_z},
92       {"__builtin_arm_cdp", "arm", arm_cdp},
93       {"__builtin_bpf_preserve_type_info", "bpf", bpf_preserve_type_info},
94       {"__builtin_HEXAGON_A2_tfr", "hexagon", hexagon_A2_tfr},
95       {"__builtin_lasx_xbz_w", "loongarch", loongarch_lasx_xbz_w},
96       {"__builtin_mips_bitrev", "mips", mips_bitrev},
97       {"__nvvm_add_rn_d", "nvvm", nvvm_add_rn_d},
98       {"__builtin_altivec_dss", "ppc", ppc_altivec_dss},
99       {"__builtin_riscv_sha512sum1r", "riscv", riscv_sha512sum1r},
100       {"__builtin_tend", "s390", s390_tend},
101       {"__builtin_ia32_pause", "x86", x86_sse2_pause},
102 
103       {"__does_not_exist", "", not_intrinsic},
104       {"__does_not_exist", "arm", not_intrinsic},
105       {"__builtin_arm_cdp", "", not_intrinsic},
106       {"__builtin_arm_cdp", "x86", not_intrinsic},
107   };
108 
109   for (const auto &[Builtin, Target, ID] : ClangTests)
110     EXPECT_EQ(ID, getIntrinsicForClangBuiltin(Target, Builtin));
111 }
112 
113 // Tests to verify getIntrinsicForMSBuiltin.
114 TEST(IntrinsicNameLookup, MSBuiltinLookup) {
115   using namespace Intrinsic;
116   static constexpr std::tuple<StringRef, StringRef, ID> MSTests[] = {
117       {"__dmb", "aarch64", aarch64_dmb},
118       {"__dmb", "arm", arm_dmb},
119       {"__dmb", "", not_intrinsic},
120       {"__does_not_exist", "", not_intrinsic},
121       {"__does_not_exist", "arm", not_intrinsic},
122   };
123   for (const auto &[Builtin, Target, ID] : MSTests)
124     EXPECT_EQ(ID, getIntrinsicForMSBuiltin(Target, Builtin));
125 }
126 
127 TEST_F(IntrinsicsTest, InstrProfInheritance) {
128   auto isInstrProfInstBase = [](const Instruction &I) {
129     return isa<InstrProfInstBase>(I);
130   };
131 #define __ISA(TYPE, PARENT)                                                    \
132   auto is##TYPE = [&](const Instruction &I) -> bool {                          \
133     return isa<TYPE>(I) && is##PARENT(I);                                      \
134   }
135   __ISA(InstrProfCntrInstBase, InstrProfInstBase);
136   __ISA(InstrProfCoverInst, InstrProfCntrInstBase);
137   __ISA(InstrProfIncrementInst, InstrProfCntrInstBase);
138   __ISA(InstrProfIncrementInstStep, InstrProfIncrementInst);
139   __ISA(InstrProfCallsite, InstrProfCntrInstBase);
140   __ISA(InstrProfTimestampInst, InstrProfCntrInstBase);
141   __ISA(InstrProfValueProfileInst, InstrProfCntrInstBase);
142   __ISA(InstrProfMCDCBitmapInstBase, InstrProfInstBase);
143   __ISA(InstrProfMCDCBitmapParameters, InstrProfMCDCBitmapInstBase);
144   __ISA(InstrProfMCDCTVBitmapUpdate, InstrProfMCDCBitmapInstBase);
145 #undef __ISA
146 
147   std::vector<
148       std::pair<Intrinsic::ID, std::function<bool(const Instruction &)>>>
149       LeafIDs = {
150           {Intrinsic::instrprof_cover, isInstrProfCoverInst},
151           {Intrinsic::instrprof_increment, isInstrProfIncrementInst},
152           {Intrinsic::instrprof_increment_step, isInstrProfIncrementInstStep},
153           {Intrinsic::instrprof_callsite, isInstrProfCallsite},
154           {Intrinsic::instrprof_mcdc_parameters,
155            isInstrProfMCDCBitmapParameters},
156           {Intrinsic::instrprof_mcdc_tvbitmap_update,
157            isInstrProfMCDCTVBitmapUpdate},
158           {Intrinsic::instrprof_timestamp, isInstrProfTimestampInst},
159           {Intrinsic::instrprof_value_profile, isInstrProfValueProfileInst}};
160   for (const auto &[ID, Checker] : LeafIDs) {
161     auto *Intr = makeIntrinsic(ID);
162     EXPECT_TRUE(Checker(*Intr));
163   }
164 }
165 
166 } // end namespace
167