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