xref: /llvm-project/llvm/unittests/Target/AArch64/InstSizes.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1 #include "AArch64Subtarget.h"
2 #include "AArch64TargetMachine.h"
3 #include "llvm/CodeGen/MIRParser/MIRParser.h"
4 #include "llvm/CodeGen/MachineModuleInfo.h"
5 #include "llvm/IR/Module.h"
6 #include "llvm/MC/TargetRegistry.h"
7 #include "llvm/Support/MemoryBuffer.h"
8 #include "llvm/Support/TargetSelect.h"
9 
10 #include "gtest/gtest.h"
11 
12 using namespace llvm;
13 
14 namespace {
15 std::unique_ptr<TargetMachine> createTargetMachine() {
16   auto TT(Triple::normalize("aarch64--"));
17   std::string CPU("generic");
18   std::string FS("+pauth,+mops,+mte");
19 
20   LLVMInitializeAArch64TargetInfo();
21   LLVMInitializeAArch64Target();
22   LLVMInitializeAArch64TargetMC();
23 
24   std::string Error;
25   const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
26 
27   return std::unique_ptr<TargetMachine>(
28       TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), std::nullopt,
29                                      std::nullopt, CodeGenOptLevel::Default));
30 }
31 
32 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
33   AArch64Subtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
34                       std::string(TM->getTargetCPU()),
35                       std::string(TM->getTargetFeatureString()), *TM,
36                       /* isLittle */ false);
37   return std::make_unique<AArch64InstrInfo>(ST);
38 }
39 
40 /// The \p InputIRSnippet is only needed for things that can't be expressed in
41 /// the \p InputMIRSnippet (global variables etc)
42 /// TODO: Some of this might be useful for other architectures as well - extract
43 ///       the platform-independent parts somewhere they can be reused.
44 void runChecks(
45     TargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet,
46     const StringRef InputMIRSnippet,
47     std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) {
48   LLVMContext Context;
49 
50   auto MIRString =
51     "--- |\n"
52     "  declare void @sizes()\n"
53     + InputIRSnippet.str() +
54     "...\n"
55     "---\n"
56     "name: sizes\n"
57     "jumpTable:\n"
58     "  kind:            block-address\n"
59     "  entries:\n"
60     "    - id:              0\n"
61     "      blocks:          [ '%bb.0' ]\n"
62     "body: |\n"
63     "  bb.0:\n"
64     + InputMIRSnippet.str();
65 
66   std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
67   std::unique_ptr<MIRParser> MParser =
68       createMIRParser(std::move(MBuffer), Context);
69   ASSERT_TRUE(MParser);
70 
71   std::unique_ptr<Module> M = MParser->parseIRModule();
72   ASSERT_TRUE(M);
73 
74   M->setTargetTriple(TM->getTargetTriple().getTriple());
75   M->setDataLayout(TM->createDataLayout());
76 
77   MachineModuleInfo MMI(TM);
78   bool Res = MParser->parseMachineFunctions(*M, MMI);
79   ASSERT_FALSE(Res);
80 
81   auto F = M->getFunction("sizes");
82   ASSERT_TRUE(F != nullptr);
83   auto &MF = MMI.getOrCreateMachineFunction(*F);
84 
85   Checks(*II, MF);
86 }
87 
88 } // anonymous namespace
89 
90 TEST(InstSizes, Authenticated) {
91   std::unique_ptr<TargetMachine> TM = createTargetMachine();
92   ASSERT_TRUE(TM);
93   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
94 
95   auto isAuthInst = [](AArch64InstrInfo &II, MachineFunction &MF) {
96     auto I = MF.begin()->begin();
97     EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
98     EXPECT_TRUE(I->getDesc().isAuthenticated());
99   };
100 
101   runChecks(TM.get(), II.get(), "",
102             "    \n"
103             "    BLRAA $x10, $x9\n",
104             isAuthInst);
105 
106   runChecks(TM.get(), II.get(), "",
107             "    \n"
108             "    RETAB implicit $lr, implicit $sp, implicit killed $x0\n",
109             isAuthInst);
110 
111   runChecks(TM.get(), II.get(), "",
112             "    \n"
113             "    frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp\n",
114             isAuthInst);
115 
116   runChecks(TM.get(), II.get(), "",
117             "    \n"
118             "    frame-destroy AUTIBSP implicit-def $lr, implicit killed $lr, implicit $sp\n",
119             isAuthInst);
120 }
121 
122 TEST(InstSizes, STACKMAP) {
123   std::unique_ptr<TargetMachine> TM = createTargetMachine();
124   ASSERT_TRUE(TM);
125   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
126 
127   runChecks(TM.get(), II.get(), "", "    STACKMAP 0, 16\n"
128                                     "    STACKMAP 1, 32\n",
129             [](AArch64InstrInfo &II, MachineFunction &MF) {
130               auto I = MF.begin()->begin();
131               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
132               ++I;
133               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
134             });
135 }
136 
137 TEST(InstSizes, PATCHPOINT) {
138   std::unique_ptr<TargetMachine> TM = createTargetMachine();
139   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
140 
141   runChecks(TM.get(), II.get(), "",
142             "    PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n"
143             "    PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n",
144             [](AArch64InstrInfo &II, MachineFunction &MF) {
145               auto I = MF.begin()->begin();
146               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
147               ++I;
148               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
149             });
150 }
151 
152 TEST(InstSizes, STATEPOINT) {
153   std::unique_ptr<TargetMachine> TM = createTargetMachine();
154   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
155 
156   runChecks(TM.get(), II.get(), "",
157             "    STATEPOINT 0, 0, 0, @sizes, 2, 0, 2, 0, 2, 0, 2, 1, 1, 8,"
158             " $sp, 24, 2, 0, 2, 1, 0, 0\n",
159             [](AArch64InstrInfo &II, MachineFunction &MF) {
160               auto I = MF.begin()->begin();
161               EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
162             });
163 }
164 
165 TEST(InstSizes, SPACE) {
166   std::unique_ptr<TargetMachine> TM = createTargetMachine();
167   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
168 
169   runChecks(TM.get(), II.get(), "",
170             "    $xzr = SPACE 1024, undef $xzr\n"
171             "    dead $xzr = SPACE 4096, $xzr\n",
172             [](AArch64InstrInfo &II, MachineFunction &MF) {
173               auto I = MF.begin()->begin();
174               EXPECT_EQ(1024u, II.getInstSizeInBytes(*I));
175               ++I;
176               EXPECT_EQ(4096u, II.getInstSizeInBytes(*I));
177             });
178 }
179 
180 TEST(InstSizes, TLSDESC_CALLSEQ) {
181   std::unique_ptr<TargetMachine> TM = createTargetMachine();
182   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
183 
184   runChecks(
185       TM.get(), II.get(),
186       "  @ThreadLocalGlobal = external thread_local global i32, align 8\n",
187       "    TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n",
188       [](AArch64InstrInfo &II, MachineFunction &MF) {
189         auto I = MF.begin()->begin();
190         EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
191       });
192 }
193 
194 TEST(InstSizes, StoreSwiftAsyncContext) {
195   std::unique_ptr<TargetMachine> TM = createTargetMachine();
196   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
197 
198   runChecks(
199       TM.get(), II.get(), "",
200       "    StoreSwiftAsyncContext $x0, $x1, 12, implicit-def $x16, "
201       "implicit-def $x17\n",
202       [](AArch64InstrInfo &II, MachineFunction &MF) {
203         auto I = MF.begin()->begin();
204         EXPECT_EQ(20u, II.getInstSizeInBytes(*I));
205       });
206 }
207 
208 TEST(InstSizes, SpeculationBarrierISBDSBEndBB) {
209   std::unique_ptr<TargetMachine> TM = createTargetMachine();
210   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
211 
212   runChecks(
213       TM.get(), II.get(), "",
214       "    SpeculationBarrierISBDSBEndBB\n"
215       "    BR $x8\n",
216       [](AArch64InstrInfo &II, MachineFunction &MF) {
217         auto I = MF.begin()->begin();
218         EXPECT_EQ(8u, II.getInstSizeInBytes(*I));
219       });
220 }
221 
222 TEST(InstSizes, SpeculationBarrierSBEndBB) {
223   std::unique_ptr<TargetMachine> TM = createTargetMachine();
224   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
225 
226   runChecks(
227       TM.get(), II.get(), "",
228       "    SpeculationBarrierSBEndBB\n"
229       "    BR $x8\n",
230       [](AArch64InstrInfo &II, MachineFunction &MF) {
231         auto I = MF.begin()->begin();
232         EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
233       });
234 }
235 
236 TEST(InstSizes, JumpTable) {
237   std::unique_ptr<TargetMachine> TM = createTargetMachine();
238   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
239 
240   runChecks(TM.get(), II.get(), "",
241             "    $x10, $x11 = JumpTableDest32 $x9, $x8, %jump-table.0\n"
242             "    $x10, $x11 = JumpTableDest16 $x9, $x8, %jump-table.0\n"
243             "    $x10, $x11 = JumpTableDest8 $x9, $x8, %jump-table.0\n",
244             [](AArch64InstrInfo &II, MachineFunction &MF) {
245               auto I = MF.begin()->begin();
246               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
247               ++I;
248               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
249               ++I;
250               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
251             });
252 }
253 
254 TEST(InstSizes, MOPSMemoryPseudos) {
255   std::unique_ptr<TargetMachine> TM = createTargetMachine();
256   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
257 
258   runChecks(TM.get(), II.get(), "",
259             "  $x0, $x1, $x2 = MOPSMemoryMovePseudo $x0, $x1, $x2, "
260             "implicit-def $nzcv\n"
261             "  $x0, $x1 = MOPSMemorySetPseudo $x0, $x1, $x2, "
262             "implicit-def $nzcv\n"
263             "  $x0, $x1, $x8 = MOPSMemoryCopyPseudo $x0, $x1, $x8, "
264             "implicit-def $nzcv\n"
265             "  $x0, $x1 = MOPSMemorySetTaggingPseudo $x0, $x1, $x2, "
266             "implicit-def $nzcv\n",
267             [](AArch64InstrInfo &II, MachineFunction &MF) {
268               auto I = MF.begin()->begin();
269               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
270               ++I;
271               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
272               ++I;
273               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
274               ++I;
275               EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
276             });
277 }
278