1 //===- llvm/unittest/IR/IntrinsicsTest.cpp - ------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
34 class IntrinsicsTest
: public ::testing::Test
{
36 std::unique_ptr
<Module
> M
;
37 BasicBlock
*BB
= nullptr;
39 void TearDown() override
{ M
.reset(); }
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);
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
);
58 return Builder
.CreateCall(Decl
, ProcessedArgs
);
60 template <typename T
> void checkIsa(const Instruction
&I
) {
61 EXPECT_TRUE(isa
<T
>(I
));
65 TEST(IntrinsicNameLookup
, Basic
) {
66 static constexpr const char *const NameTable
[] = {
67 "llvm.foo", "llvm.foo.a", "llvm.foo.b", "llvm.foo.b.a", "llvm.foo.c",
70 static constexpr std::pair
<const char *, int> Tests
[] = {
71 {"llvm.foo", 0}, {"llvm.foo.f64", 0}, {"llvm.foo.b", 2},
72 {"llvm.foo.b.a", 3}, {"llvm.foo.c", 4}, {"llvm.foo.c.f64", 4},
76 for (const auto &[Name
, ExpectedIdx
] : Tests
) {
77 int Idx
= Intrinsic::lookupLLVMIntrinsicByName(NameTable
, Name
);
78 EXPECT_EQ(ExpectedIdx
, Idx
);
79 if (!StringRef(Name
).starts_with("llvm.foo"))
81 Idx
= Intrinsic::lookupLLVMIntrinsicByName(NameTable
, Name
, "foo");
82 EXPECT_EQ(ExpectedIdx
, Idx
);
86 // Tests to verify getIntrinsicForClangBuiltin.
87 TEST(IntrinsicNameLookup
, ClangBuiltinLookup
) {
88 using namespace Intrinsic
;
89 static constexpr std::tuple
<StringRef
, StringRef
, ID
> ClangTests
[] = {
90 {"__builtin_adjust_trampoline", "", adjust_trampoline
},
91 {"__builtin_trap", "", trap
},
92 {"__builtin_arm_chkfeat", "aarch64", aarch64_chkfeat
},
93 {"__builtin_amdgcn_alignbyte", "amdgcn", amdgcn_alignbyte
},
94 {"__builtin_amdgcn_workgroup_id_z", "amdgcn", amdgcn_workgroup_id_z
},
95 {"__builtin_arm_cdp", "arm", arm_cdp
},
96 {"__builtin_bpf_preserve_type_info", "bpf", bpf_preserve_type_info
},
97 {"__builtin_HEXAGON_A2_tfr", "hexagon", hexagon_A2_tfr
},
98 {"__builtin_lasx_xbz_w", "loongarch", loongarch_lasx_xbz_w
},
99 {"__builtin_mips_bitrev", "mips", mips_bitrev
},
100 {"__nvvm_add_rn_d", "nvvm", nvvm_add_rn_d
},
101 {"__builtin_altivec_dss", "ppc", ppc_altivec_dss
},
102 {"__builtin_riscv_sha512sum1r", "riscv", riscv_sha512sum1r
},
103 {"__builtin_tend", "s390", s390_tend
},
104 {"__builtin_ia32_pause", "x86", x86_sse2_pause
},
106 {"__does_not_exist", "", not_intrinsic
},
107 {"__does_not_exist", "arm", not_intrinsic
},
108 {"__builtin_arm_cdp", "", not_intrinsic
},
109 {"__builtin_arm_cdp", "x86", not_intrinsic
},
112 for (const auto &[Builtin
, Target
, ID
] : ClangTests
)
113 EXPECT_EQ(ID
, getIntrinsicForClangBuiltin(Target
, Builtin
));
116 // Tests to verify getIntrinsicForMSBuiltin.
117 TEST(IntrinsicNameLookup
, MSBuiltinLookup
) {
118 using namespace Intrinsic
;
119 static constexpr std::tuple
<StringRef
, StringRef
, ID
> MSTests
[] = {
120 {"__dmb", "aarch64", aarch64_dmb
},
121 {"__dmb", "arm", arm_dmb
},
122 {"__dmb", "", not_intrinsic
},
123 {"__does_not_exist", "", not_intrinsic
},
124 {"__does_not_exist", "arm", not_intrinsic
},
126 for (const auto &[Builtin
, Target
, ID
] : MSTests
)
127 EXPECT_EQ(ID
, getIntrinsicForMSBuiltin(Target
, Builtin
));
130 TEST_F(IntrinsicsTest
, InstrProfInheritance
) {
131 auto isInstrProfInstBase
= [](const Instruction
&I
) {
132 return isa
<InstrProfInstBase
>(I
);
134 #define __ISA(TYPE, PARENT) \
135 auto is##TYPE = [&](const Instruction &I) -> bool { \
136 return isa<TYPE>(I) && is##PARENT(I); \
138 __ISA(InstrProfCntrInstBase
, InstrProfInstBase
);
139 __ISA(InstrProfCoverInst
, InstrProfCntrInstBase
);
140 __ISA(InstrProfIncrementInst
, InstrProfCntrInstBase
);
141 __ISA(InstrProfIncrementInstStep
, InstrProfIncrementInst
);
142 __ISA(InstrProfCallsite
, InstrProfCntrInstBase
);
143 __ISA(InstrProfTimestampInst
, InstrProfCntrInstBase
);
144 __ISA(InstrProfValueProfileInst
, InstrProfCntrInstBase
);
145 __ISA(InstrProfMCDCBitmapInstBase
, InstrProfInstBase
);
146 __ISA(InstrProfMCDCBitmapParameters
, InstrProfMCDCBitmapInstBase
);
147 __ISA(InstrProfMCDCTVBitmapUpdate
, InstrProfMCDCBitmapInstBase
);
151 std::pair
<Intrinsic::ID
, std::function
<bool(const Instruction
&)>>>
153 {Intrinsic::instrprof_cover
, isInstrProfCoverInst
},
154 {Intrinsic::instrprof_increment
, isInstrProfIncrementInst
},
155 {Intrinsic::instrprof_increment_step
, isInstrProfIncrementInstStep
},
156 {Intrinsic::instrprof_callsite
, isInstrProfCallsite
},
157 {Intrinsic::instrprof_mcdc_parameters
,
158 isInstrProfMCDCBitmapParameters
},
159 {Intrinsic::instrprof_mcdc_tvbitmap_update
,
160 isInstrProfMCDCTVBitmapUpdate
},
161 {Intrinsic::instrprof_timestamp
, isInstrProfTimestampInst
},
162 {Intrinsic::instrprof_value_profile
, isInstrProfValueProfileInst
}};
163 for (const auto &[ID
, Checker
] : LeafIDs
) {
164 auto *Intr
= makeIntrinsic(ID
);
165 EXPECT_TRUE(Checker(*Intr
));