1 #include "AArch64Subtarget.h"
2 #include "AArch64TargetMachine.h"
3 #include "llvm/CodeGen/MIRParser/MIRParser.h"
4 #include "llvm/CodeGen/MachineModuleInfo.h"
5 #include "llvm/MC/TargetRegistry.h"
6 #include "llvm/Support/MemoryBuffer.h"
7 #include "llvm/Support/TargetSelect.h"
9 #include "gtest/gtest.h"
14 std::unique_ptr
<LLVMTargetMachine
> createTargetMachine() {
15 auto TT(Triple::normalize("aarch64--"));
16 std::string
CPU("generic");
17 std::string
FS("+pauth,+mops,+mte");
19 LLVMInitializeAArch64TargetInfo();
20 LLVMInitializeAArch64Target();
21 LLVMInitializeAArch64TargetMC();
24 const Target
*TheTarget
= TargetRegistry::lookupTarget(TT
, Error
);
26 return std::unique_ptr
<LLVMTargetMachine
>(static_cast<LLVMTargetMachine
*>(
27 TheTarget
->createTargetMachine(TT
, CPU
, FS
, TargetOptions(), std::nullopt
,
28 std::nullopt
, CodeGenOptLevel::Default
)));
31 std::unique_ptr
<AArch64InstrInfo
> createInstrInfo(TargetMachine
*TM
) {
32 AArch64Subtarget
ST(TM
->getTargetTriple(), std::string(TM
->getTargetCPU()),
33 std::string(TM
->getTargetCPU()),
34 std::string(TM
->getTargetFeatureString()), *TM
,
35 /* isLittle */ false);
36 return std::make_unique
<AArch64InstrInfo
>(ST
);
39 /// The \p InputIRSnippet is only needed for things that can't be expressed in
40 /// the \p InputMIRSnippet (global variables etc)
41 /// TODO: Some of this might be useful for other architectures as well - extract
42 /// the platform-independent parts somewhere they can be reused.
44 LLVMTargetMachine
*TM
, AArch64InstrInfo
*II
, const StringRef InputIRSnippet
,
45 const StringRef InputMIRSnippet
,
46 std::function
<void(AArch64InstrInfo
&, MachineFunction
&)> Checks
) {
51 " declare void @sizes()\n"
52 + InputIRSnippet
.str() +
57 " kind: block-address\n"
60 " blocks: [ '%bb.0' ]\n"
63 + InputMIRSnippet
.str();
65 std::unique_ptr
<MemoryBuffer
> MBuffer
= MemoryBuffer::getMemBuffer(MIRString
);
66 std::unique_ptr
<MIRParser
> MParser
=
67 createMIRParser(std::move(MBuffer
), Context
);
70 std::unique_ptr
<Module
> M
= MParser
->parseIRModule();
73 M
->setTargetTriple(TM
->getTargetTriple().getTriple());
74 M
->setDataLayout(TM
->createDataLayout());
76 MachineModuleInfo
MMI(TM
);
77 bool Res
= MParser
->parseMachineFunctions(*M
, MMI
);
80 auto F
= M
->getFunction("sizes");
81 ASSERT_TRUE(F
!= nullptr);
82 auto &MF
= MMI
.getOrCreateMachineFunction(*F
);
87 } // anonymous namespace
89 TEST(InstSizes
, Authenticated
) {
90 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
92 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
94 auto isAuthInst
= [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
95 auto I
= MF
.begin()->begin();
96 EXPECT_EQ(4u, II
.getInstSizeInBytes(*I
));
97 EXPECT_TRUE(I
->getDesc().isAuthenticated());
100 runChecks(TM
.get(), II
.get(), "",
102 " BLRAA $x10, $x9\n",
105 runChecks(TM
.get(), II
.get(), "",
107 " RETAB implicit $lr, implicit $sp, implicit killed $x0\n",
110 runChecks(TM
.get(), II
.get(), "",
112 " frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp\n",
115 runChecks(TM
.get(), II
.get(), "",
117 " frame-destroy AUTIBSP implicit-def $lr, implicit killed $lr, implicit $sp\n",
121 TEST(InstSizes
, STACKMAP
) {
122 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
124 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
126 runChecks(TM
.get(), II
.get(), "", " STACKMAP 0, 16\n"
128 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
129 auto I
= MF
.begin()->begin();
130 EXPECT_EQ(16u, II
.getInstSizeInBytes(*I
));
132 EXPECT_EQ(32u, II
.getInstSizeInBytes(*I
));
136 TEST(InstSizes
, PATCHPOINT
) {
137 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
138 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
140 runChecks(TM
.get(), II
.get(), "",
141 " PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n"
142 " PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n",
143 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
144 auto I
= MF
.begin()->begin();
145 EXPECT_EQ(16u, II
.getInstSizeInBytes(*I
));
147 EXPECT_EQ(32u, II
.getInstSizeInBytes(*I
));
151 TEST(InstSizes
, STATEPOINT
) {
152 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
153 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
155 runChecks(TM
.get(), II
.get(), "",
156 " STATEPOINT 0, 0, 0, @sizes, 2, 0, 2, 0, 2, 0, 2, 1, 1, 8,"
157 " $sp, 24, 2, 0, 2, 1, 0, 0\n",
158 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
159 auto I
= MF
.begin()->begin();
160 EXPECT_EQ(4u, II
.getInstSizeInBytes(*I
));
164 TEST(InstSizes
, SPACE
) {
165 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
166 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
168 runChecks(TM
.get(), II
.get(), "",
169 " $xzr = SPACE 1024, undef $xzr\n"
170 " dead $xzr = SPACE 4096, $xzr\n",
171 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
172 auto I
= MF
.begin()->begin();
173 EXPECT_EQ(1024u, II
.getInstSizeInBytes(*I
));
175 EXPECT_EQ(4096u, II
.getInstSizeInBytes(*I
));
179 TEST(InstSizes
, TLSDESC_CALLSEQ
) {
180 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
181 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
185 " @ThreadLocalGlobal = external thread_local global i32, align 8\n",
186 " TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n",
187 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
188 auto I
= MF
.begin()->begin();
189 EXPECT_EQ(16u, II
.getInstSizeInBytes(*I
));
193 TEST(InstSizes
, StoreSwiftAsyncContext
) {
194 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
195 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
198 TM
.get(), II
.get(), "",
199 " StoreSwiftAsyncContext $x0, $x1, 12, implicit-def $x16, "
200 "implicit-def $x17\n",
201 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
202 auto I
= MF
.begin()->begin();
203 EXPECT_EQ(20u, II
.getInstSizeInBytes(*I
));
207 TEST(InstSizes
, SpeculationBarrierISBDSBEndBB
) {
208 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
209 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
212 TM
.get(), II
.get(), "",
213 " SpeculationBarrierISBDSBEndBB\n"
215 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
216 auto I
= MF
.begin()->begin();
217 EXPECT_EQ(8u, II
.getInstSizeInBytes(*I
));
221 TEST(InstSizes
, SpeculationBarrierSBEndBB
) {
222 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
223 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
226 TM
.get(), II
.get(), "",
227 " SpeculationBarrierSBEndBB\n"
229 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
230 auto I
= MF
.begin()->begin();
231 EXPECT_EQ(4u, II
.getInstSizeInBytes(*I
));
235 TEST(InstSizes
, JumpTable
) {
236 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
237 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
239 runChecks(TM
.get(), II
.get(), "",
240 " $x10, $x11 = JumpTableDest32 $x9, $x8, %jump-table.0\n"
241 " $x10, $x11 = JumpTableDest16 $x9, $x8, %jump-table.0\n"
242 " $x10, $x11 = JumpTableDest8 $x9, $x8, %jump-table.0\n",
243 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
244 auto I
= MF
.begin()->begin();
245 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
247 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
249 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
253 TEST(InstSizes
, MOPSMemoryPseudos
) {
254 std::unique_ptr
<LLVMTargetMachine
> TM
= createTargetMachine();
255 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
257 runChecks(TM
.get(), II
.get(), "",
258 " $x0, $x1, $x2 = MOPSMemoryMovePseudo $x0, $x1, $x2, "
259 "implicit-def $nzcv\n"
260 " $x0, $x1 = MOPSMemorySetPseudo $x0, $x1, $x2, "
261 "implicit-def $nzcv\n"
262 " $x0, $x1, $x8 = MOPSMemoryCopyPseudo $x0, $x1, $x8, "
263 "implicit-def $nzcv\n"
264 " $x0, $x1 = MOPSMemorySetTaggingPseudo $x0, $x1, $x2, "
265 "implicit-def $nzcv\n",
266 [](AArch64InstrInfo
&II
, MachineFunction
&MF
) {
267 auto I
= MF
.begin()->begin();
268 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
270 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
272 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));
274 EXPECT_EQ(12u, II
.getInstSizeInBytes(*I
));