xref: /llvm-project/llvm/unittests/Target/ARM/InstSizes.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1 #include "ARMInstrInfo.h"
2 #include "ARMSubtarget.h"
3 #include "ARMTargetMachine.h"
4 #include "llvm/CodeGen/MIRParser/MIRParser.h"
5 #include "llvm/CodeGen/MachineModuleInfo.h"
6 #include "llvm/IR/Module.h"
7 #include "llvm/MC/TargetRegistry.h"
8 #include "llvm/Support/MemoryBuffer.h"
9 #include "llvm/Support/TargetSelect.h"
10 
11 #include "gtest/gtest.h"
12 
13 using namespace llvm;
14 
15 namespace {
16 /// The \p InputIRSnippet is only needed for things that can't be expressed in
17 /// the \p InputMIRSnippet (global variables etc)
18 /// TODO: Some of this might be useful for other architectures as well - extract
19 ///       the platform-independent parts somewhere they can be reused.
20 void runChecks(
21     TargetMachine *TM, const ARMBaseInstrInfo *II,
22     const StringRef InputIRSnippet, const StringRef InputMIRSnippet,
23     unsigned Expected,
24     std::function<void(const ARMBaseInstrInfo &, MachineFunction &, unsigned &)>
25         Checks) {
26   LLVMContext Context;
27 
28   auto MIRString = "--- |\n"
29                    "  declare void @sizes()\n" +
30                    InputIRSnippet.str() +
31                    "...\n"
32                    "---\n"
33                    "name: sizes\n"
34                    "constants:\n"
35                    "  - id:        0\n"
36                    "    value:     i32 12345678\n"
37                    "    alignment: 4\n"
38                    "jumpTable:\n"
39                    "  kind:    inline\n"
40                    "  entries:\n"
41                    "    - id:     0\n"
42                    "      blocks: [ '%bb.0' ]\n"
43                    "body: |\n"
44                    "  bb.0:\n" +
45                    InputMIRSnippet.str();
46 
47   std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
48   std::unique_ptr<MIRParser> MParser =
49       createMIRParser(std::move(MBuffer), Context);
50   ASSERT_TRUE(MParser);
51 
52   std::unique_ptr<Module> M = MParser->parseIRModule();
53   ASSERT_TRUE(M);
54 
55   M->setTargetTriple(TM->getTargetTriple().getTriple());
56   M->setDataLayout(TM->createDataLayout());
57 
58   MachineModuleInfo MMI(TM);
59   bool Res = MParser->parseMachineFunctions(*M, MMI);
60   ASSERT_FALSE(Res);
61 
62   auto F = M->getFunction("sizes");
63   ASSERT_TRUE(F != nullptr);
64   auto &MF = MMI.getOrCreateMachineFunction(*F);
65 
66   Checks(*II, MF, Expected);
67 }
68 
69 } // anonymous namespace
70 
71 TEST(InstSizes, PseudoInst) {
72   LLVMInitializeARMTargetInfo();
73   LLVMInitializeARMTarget();
74   LLVMInitializeARMTargetMC();
75 
76   auto TT(Triple::normalize("thumbv8.1m.main-none-none-eabi"));
77   std::string Error;
78   const Target *T = TargetRegistry::lookupTarget(TT, Error);
79   if (!T) {
80     dbgs() << Error;
81     GTEST_SKIP();
82   }
83 
84   TargetOptions Options;
85   auto TM = std::unique_ptr<TargetMachine>(
86       T->createTargetMachine(TT, "generic", "", Options, std::nullopt,
87                              std::nullopt, CodeGenOptLevel::Default));
88   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
89                   std::string(TM->getTargetFeatureString()),
90                   *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
91   const ARMBaseInstrInfo *II = ST.getInstrInfo();
92 
93   auto cmpInstSize = [](const ARMBaseInstrInfo &II, MachineFunction &MF,
94                         unsigned &Expected) {
95     auto I = MF.begin()->begin();
96     EXPECT_EQ(Expected, II.getInstSizeInBytes(*I));
97   };
98 
99   runChecks(TM.get(), II, "",
100             "    $r0 = MOVi16_ga_pcrel"
101             " target-flags(arm-lo16, arm-nonlazy) @sizes, 0\n",
102             4u, cmpInstSize);
103 
104   runChecks(TM.get(), II, "",
105             "    $r0 = MOVTi16_ga_pcrel $r0,"
106             " target-flags(arm-hi16, arm-nonlazy) @sizes, 0\n",
107             4u, cmpInstSize);
108 
109   runChecks(TM.get(), II, "",
110             "    $r0 = t2MOVi16_ga_pcrel"
111             " target-flags(arm-lo16, arm-nonlazy) @sizes, 0\n",
112             4u, cmpInstSize);
113 
114   runChecks(TM.get(), II, "",
115             "    $r0 = t2MOVTi16_ga_pcrel $r0,"
116             " target-flags(arm-hi16, arm-nonlazy) @sizes, 0\n",
117             4u, cmpInstSize);
118 
119   runChecks(TM.get(), II, "", "    $r0 = MOVi32imm 2\n", 8u, cmpInstSize);
120 
121   runChecks(TM.get(), II, "", "    $r0 = t2MOVi32imm 2\n", 8u, cmpInstSize);
122 
123   runChecks(TM.get(), II, "",
124             "    SpeculationBarrierISBDSBEndBB\n"
125             "    tBX_RET 14, $noreg, implicit $r0\n",
126             8u, cmpInstSize);
127 
128   runChecks(TM.get(), II, "",
129             "    t2SpeculationBarrierISBDSBEndBB\n"
130             "    tBX_RET 14, $noreg, implicit $r0\n",
131             8u, cmpInstSize);
132 
133   runChecks(TM.get(), II, "",
134             "    SpeculationBarrierSBEndBB\n"
135             "    tBX_RET 14, $noreg, implicit $r0\n",
136             4u, cmpInstSize);
137 
138   runChecks(TM.get(), II, "",
139             "    t2SpeculationBarrierSBEndBB\n"
140             "    tBX_RET 14, $noreg, implicit $r0\n",
141             4u, cmpInstSize);
142 
143   runChecks(TM.get(), II, "",
144             "    Int_eh_sjlj_longjmp $r0, $r1, implicit-def $r7,"
145             " implicit-def $lr, implicit-def $sp\n",
146             16u, cmpInstSize);
147 
148   runChecks(TM.get(), II, "",
149             "    tInt_eh_sjlj_longjmp $r0, $r1, implicit-def $r7,"
150             " implicit-def $lr, implicit-def $sp\n",
151             10u, cmpInstSize);
152 
153   runChecks(TM.get(), II, "",
154             "    tInt_WIN_eh_sjlj_longjmp $r0, $r1, implicit-def $r11,"
155             " implicit-def $lr, implicit-def $sp\n",
156             12u, cmpInstSize);
157 
158   runChecks(TM.get(), II, "",
159             "    Int_eh_sjlj_setjmp $r0, $r1, implicit-def $r0,"
160             " implicit-def $r1, implicit-def $r2, implicit-def $r3,"
161             " implicit-def $r4, implicit-def $r5, implicit-def $r6,"
162             " implicit-def $r7, implicit-def $r8, implicit-def $r9,"
163             " implicit-def $r10, implicit-def $r11, implicit-def $r12,"
164             " implicit-def $lr, implicit-def $cpsr, implicit-def $q0,"
165             " implicit-def $q1, implicit-def $q2, implicit-def $q3,"
166             " implicit-def $q4, implicit-def $q5, implicit-def $q6,"
167             " implicit-def $q7, implicit-def $q8, implicit-def $q9,"
168             " implicit-def $q10, implicit-def $q11, implicit-def $q12,"
169             " implicit-def $q13, implicit-def $q14, implicit-def $q15\n"
170             "    tBX_RET 14, $noreg, implicit $r0\n",
171             20u, cmpInstSize);
172 
173   runChecks(TM.get(), II, "",
174             "    Int_eh_sjlj_setjmp_nofp $r0, $r1, implicit-def $r0,"
175             " implicit-def $r1, implicit-def $r2, implicit-def $r3,"
176             " implicit-def $r4, implicit-def $r5, implicit-def $r6,"
177             " implicit-def $r7, implicit-def $r8, implicit-def $r9,"
178             " implicit-def $r10, implicit-def $r11, implicit-def $r12,"
179             " implicit-def $lr, implicit-def $cpsr\n"
180             "    tBX_RET 14, $noreg, implicit $r0\n",
181             20u, cmpInstSize);
182 
183   runChecks(TM.get(), II, "",
184             "    tInt_eh_sjlj_setjmp $r0, $r1, implicit-def $r0,"
185             " implicit-def $r1, implicit-def $r2, implicit-def $r3,"
186             " implicit-def $r4, implicit-def $r5, implicit-def $r6,"
187             " implicit-def $r7, implicit-def $r12, implicit-def $cpsr\n"
188             "    tBX_RET 14, $noreg, implicit $r0\n",
189             12u, cmpInstSize);
190 
191   runChecks(TM.get(), II, "",
192             "    t2Int_eh_sjlj_setjmp $r0, $r1, implicit-def $r0,"
193             " implicit-def $r1, implicit-def $r2, implicit-def $r3,"
194             " implicit-def $r4, implicit-def $r5, implicit-def $r6,"
195             " implicit-def $r7, implicit-def $r8, implicit-def $r9,"
196             " implicit-def $r10, implicit-def $r11, implicit-def $r12,"
197             " implicit-def $lr, implicit-def $cpsr, implicit-def $q0,"
198             " implicit-def $q1, implicit-def $q2, implicit-def $q3,"
199             " implicit-def $q8, implicit-def $q9, implicit-def $q10,"
200             " implicit-def $q11, implicit-def $q12, implicit-def $q13,"
201             " implicit-def $q14, implicit-def $q15\n"
202             "    tBX_RET 14, $noreg, implicit $r0\n",
203             12u, cmpInstSize);
204 
205   runChecks(TM.get(), II, "",
206             "    t2Int_eh_sjlj_setjmp_nofp $r0, $r1, implicit-def $r0,"
207             " implicit-def $r1, implicit-def $r2, implicit-def $r3,"
208             " implicit-def $r4, implicit-def $r5, implicit-def $r6,"
209             " implicit-def $r7, implicit-def $r8, implicit-def $r9,"
210             " implicit-def $r10, implicit-def $r11, implicit-def $r12,"
211             " implicit-def $lr, implicit-def $cpsr\n"
212             "    tBX_RET 14, $noreg, implicit $r0\n",
213             12u, cmpInstSize);
214 
215   runChecks(TM.get(), II, "", "  CONSTPOOL_ENTRY 3, %const.0, 8\n", 8u,
216             cmpInstSize);
217 
218   runChecks(TM.get(), II, "", "  JUMPTABLE_ADDRS 0, %jump-table.0, 123\n", 123u,
219             cmpInstSize);
220 
221   runChecks(TM.get(), II, "", "  JUMPTABLE_INSTS 0, %jump-table.0, 456\n", 456u,
222             cmpInstSize);
223 
224   runChecks(TM.get(), II, "", "  JUMPTABLE_TBB 0, %jump-table.0, 789\n", 789u,
225             cmpInstSize);
226 
227   runChecks(TM.get(), II, "", "  JUMPTABLE_TBH 0, %jump-table.0, 188\n", 188u,
228             cmpInstSize);
229 
230   runChecks(TM.get(), II, "", "  $r0 = SPACE 40, undef $r0\n", 40u,
231             cmpInstSize);
232 
233   runChecks(TM.get(), II, "", "  INLINEASM &\"movs  r0, #42\", 1\n", 6u,
234             cmpInstSize);
235 
236   runChecks(TM.get(), II,
237             "  define void @foo() {\n"
238             "  entry:\n"
239             "    ret void\n"
240             "  }\n",
241             "  INLINEASM_BR &\"b ${0:l}\", 1, 13, blockaddress(@foo, "
242             "%ir-block.entry)\n",
243             6u, cmpInstSize);
244 }
245