1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "unit_test.h"
17 #include "optimizer/ir_builder/inst_builder-inl.h"
18
19 namespace panda::compiler {
operator ==(const Input & lhs,const Inst * rhs)20 inline bool operator==(const Input &lhs, const Inst *rhs)
21 {
22 return lhs.GetInst() == rhs;
23 }
24
25 class InstTest : public GraphTest {
26 };
27
TEST_F(InstTest,Dataflow)28 TEST_F(InstTest, Dataflow)
29 {
30 /**
31 * '=' is a definition
32 *
33 * [2]
34 * |
35 * /---------------\
36 * | |
37 * [3]= [4]=
38 * | |
39 * | /---------\
40 * [5] | |
41 * | | [6] (need for removing #6)
42 * | | |
43 * | | [7]=
44 * | | |
45 * \---------[8]--------/
46 * PHI(1,2,4)
47 *
48 */
49 GRAPH(GetGraph())
50 {
51 CONSTANT(0, 12);
52 CONSTANT(1, 13);
53
54 BASIC_BLOCK(2, 3, 4)
55 {
56 INST(2, Opcode::Add).u64().Inputs(0, 1);
57 INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
58 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
59 }
60 BASIC_BLOCK(3, 5)
61 {
62 INST(3, Opcode::Not).u64().Inputs(0);
63 }
64 BASIC_BLOCK(4, 8, 6)
65 {
66 INST(4, Opcode::Not).u64().Inputs(1);
67 INST(11, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
68 INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11);
69 }
70 BASIC_BLOCK(5, 8)
71 {
72 INST(7, Opcode::Sub).u64().Inputs(3, 2);
73 }
74 BASIC_BLOCK(6, 7) {}
75 BASIC_BLOCK(7, 8)
76 {
77 INST(5, Opcode::Not).u64().Inputs(4);
78 }
79 BASIC_BLOCK(8, -1)
80 {
81 INST(6, Opcode::Phi).u64().Inputs({{5, 3}, {4, 4}, {7, 5}});
82 INST(16, Opcode::ReturnVoid);
83 }
84 }
85
86 // Check constructed dataflow
87 ASSERT_TRUE(CheckUsers(INS(0), {2, 3, 8, 11}));
88 ASSERT_TRUE(CheckUsers(INS(1), {2, 4, 8, 11}));
89 ASSERT_TRUE(CheckUsers(INS(2), {7}));
90 ASSERT_TRUE(CheckUsers(INS(3), {6, 7}));
91 ASSERT_TRUE(CheckUsers(INS(4), {5, 6}));
92 ASSERT_TRUE(CheckUsers(INS(5), {6}));
93 ASSERT_TRUE(CheckInputs(INS(2), {0, 1}));
94 ASSERT_TRUE(CheckInputs(INS(3), {0}));
95 ASSERT_TRUE(CheckInputs(INS(7), {3, 2}));
96 ASSERT_TRUE(CheckInputs(INS(4), {1}));
97 ASSERT_TRUE(CheckInputs(INS(5), {4}));
98 ASSERT_TRUE(CheckInputs(INS(6), {3, 4, 5}));
99 ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(5)), &INS(3));
100 ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(4)), &INS(4));
101 ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(7)), &INS(5));
102
103 { // Test iterating over users of constant instruction
104 const Inst *inst = &INS(2);
105 for (auto &user : inst->GetUsers()) {
106 ASSERT_EQ(inst, user.GetInput());
107 }
108 }
109
110 { // Test iterating over users of non-constant instruction
111 Inst *inst = &INS(2);
112 for (auto &user : inst->GetUsers()) {
113 user.GetInst()->SetId(user.GetInst()->GetId());
114 }
115 }
116
117 // 1. Remove instruction #3, replace its users by its input
118 INS(3).ReplaceUsers(INS(3).GetInput(0).GetInst());
119 INS(3).GetBasicBlock()->RemoveInst(&INS(3));
120 ASSERT_TRUE(INS(6).GetInput(0).GetInst() == &INS(0));
121 ASSERT_TRUE(INS(3).GetInput(0).GetInst() == nullptr);
122 ASSERT_TRUE(CheckUsers(INS(0), {2, 6, 7, 8, 11}));
123 ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(5)), &INS(0));
124 GraphChecker(GetGraph()).Check();
125
126 // TODO(A.Popov): refactor RemovePredsBlocks
127 // 2. Remove basic block #4, phi should be fixed properly
128 // INS(5).RemoveInputs()
129 // INS(5).GetBasicBlock()->EraseInst(&INS(5))
130 // GetGraph()->DisconnectBlock(&BB(7))
131 // ASSERT_TRUE(INS(6).GetInputsCount() == 2)
132 // static_cast<PhiInst&>(INS(6)).GetPhiInput(&BB(5)), &INS(0))
133 // static_cast<PhiInst&>(INS(6)).GetPhiInput(&BB(4)), &INS(4))
134 GraphChecker(GetGraph()).Check();
135
136 // 3. Append additional inputs into PHI, thereby force it to reallocate inputs storage, dataflow is not valid from
137 // this moment
138 for (int i = 0; i < 4; ++i) {
139 INS(6).AppendInput(&INS(0));
140 }
141 }
142
TEST_F(InstTest,Arithmetics)143 TEST_F(InstTest, Arithmetics)
144 {
145 GRAPH(GetGraph())
146 {
147 CONSTANT(0, 12);
148 CONSTANT(1, 17.23);
149
150 BASIC_BLOCK(2, -1)
151 {
152 INST(2, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(1);
153 INST(3, Opcode::Add).u64().Inputs(0, 2);
154 INST(4, Opcode::ReturnVoid);
155 }
156 }
157 }
158
TEST_F(InstTest,Memory)159 TEST_F(InstTest, Memory)
160 {
161 GRAPH(GetGraph())
162 {
163 PARAMETER(0, 0).ref(); // array
164 PARAMETER(1, 1).u64(); // index
165 BASIC_BLOCK(2, -1)
166 {
167 INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
168 INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
169 INST(4, Opcode::LenArray).s32().Inputs(3);
170 INST(5, Opcode::BoundsCheck).s32().Inputs(4, 1, 2);
171 INST(6, Opcode::LoadArray).u64().Inputs(3, 5);
172 INST(7, Opcode::Add).u64().Inputs(6, 6);
173 INST(8, Opcode::StoreArray).u64().Inputs(3, 5, 7);
174 INST(9, Opcode::ReturnVoid);
175 }
176 }
177 }
178
TEST_F(InstTest,Const)179 TEST_F(InstTest, Const)
180 {
181 int32_t int32_const[3] = {-5, 0, 5};
182 int64_t int64_const[3] = {-5, 0, 5};
183 GRAPH(GetGraph())
184 {
185 BASIC_BLOCK(2, -1)
186 {
187 INST(0, Opcode::ReturnVoid);
188 }
189 }
190 auto start = GetGraph()->GetStartBlock();
191 for (auto i = 0; i < 3; i++) {
192 int32_t val = int32_const[i];
193 auto const1 = GetGraph()->FindOrCreateConstant(val);
194 ASSERT_EQ(const1->GetType(), DataType::INT64);
195 ASSERT_EQ(const1->GetBasicBlock(), start);
196 uint64_t val1 = int64_const[i];
197 auto const2 = GetGraph()->FindOrCreateConstant(val1);
198 ASSERT_EQ(const2->GetType(), DataType::INT64);
199 ASSERT_EQ(const1, const2);
200 ASSERT_EQ(const1->GetIntValue(), val1);
201 }
202 GraphChecker(GetGraph()).Check();
203 float float_const[3] = {-5.5f, 0.1f, 5.2f};
204 for (auto i = 0; i < 3; i++) {
205 float val = float_const[i];
206 auto const1 = GetGraph()->FindOrCreateConstant(val);
207 ASSERT_EQ(const1->GetType(), DataType::FLOAT32);
208 ASSERT_EQ(const1->GetBasicBlock(), start);
209 auto const2 = GetGraph()->FindOrCreateConstant(val);
210 ASSERT_EQ(const1, const2);
211 ASSERT_EQ(const1->GetFloatValue(), val);
212 }
213 GraphChecker(GetGraph()).Check();
214 double double_const[3] = {-5.5, 0.1, 5.2};
215 for (auto i = 0; i < 3; i++) {
216 double val = double_const[i];
217 auto const1 = GetGraph()->FindOrCreateConstant(val);
218 ASSERT_EQ(const1->GetType(), DataType::FLOAT64);
219 ASSERT_EQ(const1->GetBasicBlock(), start);
220 auto const2 = GetGraph()->FindOrCreateConstant(val);
221 ASSERT_EQ(const1, const2);
222 ASSERT_EQ(const1->GetDoubleValue(), val);
223 }
224 int i = 0;
225 for (auto current_const = GetGraph()->GetFirstConstInst(); current_const != nullptr;
226 current_const = current_const->GetNextConst()) {
227 i++;
228 }
229 ASSERT_EQ(i, 9);
230 }
231
TEST_F(InstTest,Const32)232 TEST_F(InstTest, Const32)
233 {
234 int32_t int32_const[3] = {-5, 0, 5};
235 int64_t int64_const[3] = {-5, 0, 5};
236 auto graph = CreateEmptyBytecodeGraph();
237
238 GRAPH(graph)
239 {
240 BASIC_BLOCK(2, -1)
241 {
242 INST(0, Opcode::ReturnVoid);
243 }
244 }
245 auto start = graph->GetStartBlock();
246 for (auto i = 0; i < 3; i++) {
247 // add first int32 constant
248 int32_t val = int32_const[i];
249 auto const1 = graph->FindOrCreateConstant(val);
250 ASSERT_EQ(const1->GetType(), DataType::INT32);
251 ASSERT_EQ(const1->GetBasicBlock(), start);
252 uint64_t val1 = int64_const[i];
253 // add int64 constant, graph creates new constant
254 auto const2 = graph->FindOrCreateConstant(val1);
255 ASSERT_EQ(const2->GetType(), DataType::INT64);
256 ASSERT_NE(const1, const2);
257 ASSERT_EQ(const2->GetBasicBlock(), start);
258 ASSERT_EQ(const1->GetIntValue(), val1);
259 // add second int32 constant, graph doesn't create new constant
260 int32_t val2 = int32_const[i];
261 auto const3 = graph->FindOrCreateConstant(val2);
262 ASSERT_EQ(const3, const1);
263 ASSERT_EQ(const1->GetInt32Value(), val2);
264 }
265 GraphChecker(graph).Check();
266 }
267
TEST_F(InstTest,ReturnVoid)268 TEST_F(InstTest, ReturnVoid)
269 {
270 GRAPH(GetGraph())
271 {
272 BASIC_BLOCK(2, -1)
273 {
274 INST(0, Opcode::ReturnVoid);
275 }
276 }
277 }
278
TEST_F(InstTest,ReturnFloat)279 TEST_F(InstTest, ReturnFloat)
280 {
281 GRAPH(GetGraph())
282 {
283 CONSTANT(0, 1.1f);
284 BASIC_BLOCK(2, -1)
285 {
286 INST(1, Opcode::Return).f32().Inputs(0);
287 }
288 }
289 }
290
TEST_F(InstTest,ReturnDouble)291 TEST_F(InstTest, ReturnDouble)
292 {
293 GRAPH(GetGraph())
294 {
295 CONSTANT(0, 1.1);
296 BASIC_BLOCK(2, -1)
297 {
298 INST(1, Opcode::Return).f64().Inputs(0);
299 }
300 }
301 }
302
TEST_F(InstTest,ReturnLong)303 TEST_F(InstTest, ReturnLong)
304 {
305 uint64_t i = 1;
306 GRAPH(GetGraph())
307 {
308 CONSTANT(0, i);
309 BASIC_BLOCK(2, -1)
310 {
311 INST(1, Opcode::Return).u64().Inputs(0);
312 }
313 }
314 }
315
TEST_F(InstTest,ReturnInt)316 TEST_F(InstTest, ReturnInt)
317 {
318 int32_t i = 1;
319 GRAPH(GetGraph())
320 {
321 CONSTANT(0, i);
322 BASIC_BLOCK(2, -1)
323 {
324 INST(1, Opcode::Return).u32().Inputs(0);
325 }
326 }
327 }
328
TEST_F(InstTest,ArrayChecks)329 TEST_F(InstTest, ArrayChecks)
330 {
331 GRAPH(GetGraph())
332 {
333 PARAMETER(0, 0).ref(); // array
334 PARAMETER(1, 1).u64(); // index
335 BASIC_BLOCK(2, -1)
336 {
337 INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
338 INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
339 INST(4, Opcode::LenArray).s32().Inputs(3);
340 INST(5, Opcode::BoundsCheck).s32().Inputs(4, 1, 2);
341 INST(6, Opcode::LoadArray).u64().Inputs(3, 5);
342 INST(7, Opcode::Add).u64().Inputs(6, 6);
343 INST(8, Opcode::StoreArray).u64().Inputs(3, 5, 7);
344 INST(9, Opcode::ReturnVoid);
345 }
346 }
347 }
348
TEST_F(InstTest,ZeroCheck)349 TEST_F(InstTest, ZeroCheck)
350 {
351 GRAPH(GetGraph())
352 {
353 PARAMETER(0, 0).u64();
354 PARAMETER(1, 1).u64();
355 BASIC_BLOCK(2, -1)
356 {
357 INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
358 INST(3, Opcode::ZeroCheck).u64().Inputs(0, 2);
359 INST(4, Opcode::Div).u64().Inputs(1, 3);
360 INST(5, Opcode::Mod).u64().Inputs(1, 3);
361 INST(6, Opcode::ReturnVoid);
362 }
363 }
364 }
365
TEST_F(InstTest,Parametr)366 TEST_F(InstTest, Parametr)
367 {
368 GRAPH(GetGraph())
369 {
370 PARAMETER(0, 0).u64();
371 PARAMETER(1, 1).u32();
372 PARAMETER(2, 4).u16();
373 PARAMETER(3, 5).u8();
374 PARAMETER(4, 8).s64();
375 PARAMETER(5, 10).s32();
376 PARAMETER(6, 11).s16();
377 PARAMETER(7, 24).s8();
378 PARAMETER(8, 27).b();
379 PARAMETER(9, 28).f64();
380 PARAMETER(10, 29).f32();
381 PARAMETER(11, 40).ref();
382 BASIC_BLOCK(2, -1)
383 {
384 INST(12, Opcode::Add).u32().Inputs(1, 5);
385 INST(13, Opcode::ReturnVoid);
386 }
387 }
388 }
389
TEST_F(InstTest,LenArray)390 TEST_F(InstTest, LenArray)
391 {
392 GRAPH(GetGraph())
393 {
394 PARAMETER(0, 40).ref();
395 BASIC_BLOCK(2, -1)
396 {
397 INST(1, Opcode::LenArray).s32().Inputs(0);
398 INST(2, Opcode::ReturnVoid);
399 }
400 }
401 }
402
TEST_F(InstTest,Call)403 TEST_F(InstTest, Call)
404 {
405 GRAPH(GetGraph())
406 {
407 PARAMETER(0, 1).ref();
408 PARAMETER(1, 2).u32();
409 PARAMETER(2, 4).u16();
410 PARAMETER(3, 5).u8();
411 PARAMETER(4, 8).s64();
412 BASIC_BLOCK(2, -1)
413 {
414 using namespace DataType;
415 INST(8, Opcode::SaveState).NoVregs();
416 INST(5, Opcode::CallVirtual).s32().InputsAutoType(0, 2, 4, 8);
417 INST(6, Opcode::CallStatic).b().InputsAutoType(1, 3, 4, 5, 8);
418 INST(7, Opcode::ReturnVoid);
419 }
420 }
421 }
422
TEST_F(InstTest,BinaryImmOperation)423 TEST_F(InstTest, BinaryImmOperation)
424 {
425 GRAPH(GetGraph())
426 {
427 PARAMETER(0, 1).u64();
428 PARAMETER(1, 4).s32();
429 BASIC_BLOCK(2, -1)
430 {
431 INST(2, Opcode::AddI).s32().Imm(10ULL).Inputs(1);
432 INST(3, Opcode::SubI).s32().Imm(15ULL).Inputs(2);
433 INST(4, Opcode::AndI).u64().Imm(15ULL).Inputs(0);
434 INST(5, Opcode::OrI).u64().Imm(1ULL).Inputs(4);
435 INST(6, Opcode::XorI).u64().Imm(10ULL).Inputs(5);
436 INST(7, Opcode::ShlI).u64().Imm(5ULL).Inputs(6);
437 INST(8, Opcode::ShrI).u64().Imm(5ULL).Inputs(7);
438 INST(9, Opcode::AShrI).s32().Imm(4ULL).Inputs(3);
439 INST(10, Opcode::ReturnVoid);
440 }
441 }
442 }
443
TEST_F(InstTest,Fcmp)444 TEST_F(InstTest, Fcmp)
445 {
446 GRAPH(GetGraph())
447 {
448 PARAMETER(0, 0).f32();
449 PARAMETER(1, 1).f32();
450 PARAMETER(2, 2).f64();
451 PARAMETER(3, 3).f64();
452 BASIC_BLOCK(2, -1)
453 {
454 INST(4, Opcode::Cmp).s32().Inputs(0, 1);
455 INST(5, Opcode::Cmp).s32().Inputs(2, 3);
456 INST(6, Opcode::ReturnVoid);
457 }
458 }
459 GraphChecker(GetGraph()).Check();
460 auto inst4 = static_cast<CmpInst *>(&INS(4));
461 auto inst5 = static_cast<CmpInst *>(&INS(5));
462 inst4->SetFcmpl();
463 ASSERT_EQ(inst4->IsFcmpg(), false);
464 ASSERT_EQ(inst4->IsFcmpl(), true);
465 inst4->SetFcmpl(true);
466 ASSERT_EQ(inst4->IsFcmpg(), false);
467 ASSERT_EQ(inst4->IsFcmpl(), true);
468 inst4->SetFcmpl(false);
469 ASSERT_EQ(inst4->IsFcmpg(), true);
470 ASSERT_EQ(inst4->IsFcmpl(), false);
471 inst5->SetFcmpg();
472 ASSERT_EQ(inst5->IsFcmpg(), true);
473 ASSERT_EQ(inst5->IsFcmpl(), false);
474 inst5->SetFcmpg(true);
475 ASSERT_EQ(inst5->IsFcmpg(), true);
476 ASSERT_EQ(inst5->IsFcmpl(), false);
477 inst5->SetFcmpg(false);
478 ASSERT_EQ(inst5->IsFcmpg(), false);
479 ASSERT_EQ(inst5->IsFcmpl(), true);
480 }
481
TEST_F(InstTest,SpillFill)482 TEST_F(InstTest, SpillFill)
483 {
484 Register R0 = 0;
485 Register R1 = 1;
486 StackSlot slot0 = 0;
487 StackSlot slot1 = 1;
488
489 auto spill_fill_inst = GetGraph()->CreateInstSpillFill();
490 spill_fill_inst->AddFill(slot0, R0, DataType::UINT64);
491 spill_fill_inst->AddMove(R0, R1, DataType::UINT64);
492 spill_fill_inst->AddSpill(R1, slot1, DataType::UINT64);
493
494 ASSERT_EQ(spill_fill_inst->GetSpillFills().size(), 3U);
495 }
496
TEST_F(InstTest,RemovePhiInput)497 TEST_F(InstTest, RemovePhiInput)
498 {
499 GRAPH(GetGraph())
500 {
501 CONSTANT(0, 0);
502 CONSTANT(1, 1);
503 CONSTANT(2, 2);
504 BASIC_BLOCK(2, 3, 5)
505 {
506 INST(5, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
507 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
508 }
509 BASIC_BLOCK(3, 5) {}
510 BASIC_BLOCK(5, -1)
511 {
512 INST(3, Opcode::Phi).u64().Inputs({{2, 0}, {3, 1}});
513 INST(4, Opcode::ReturnVoid);
514 }
515 }
516 auto init_inputs = INS(3).GetInputs();
517 auto init_preds = BB(5).GetPredsBlocks();
518
519 auto pred_bb_idx = INS(3).CastToPhi()->GetPredBlockIndex(&BB(3));
520 BB(5).RemovePred(&BB(3));
521 INS(3).RemoveInput(pred_bb_idx);
522
523 auto curr_inputs = INS(3).GetInputs();
524 auto curr_preds = BB(5).GetPredsBlocks();
525 for (size_t idx = 0; idx < curr_inputs.size(); idx++) {
526 if (idx != pred_bb_idx) {
527 ASSERT_EQ(init_inputs[idx].GetInst(), curr_inputs[idx].GetInst());
528 ASSERT_EQ(init_preds[idx], curr_preds[idx]);
529 } else {
530 ASSERT_EQ(init_inputs.rbegin()->GetInst(), curr_inputs[idx].GetInst());
531 ASSERT_EQ(init_preds.back(), curr_preds[idx]);
532 }
533 }
534 }
535
536 /**
537 * Test creating instruction with huge dynamic inputs amount
538 */
TEST_F(InstTest,HugeDynamicOperandsAmount)539 TEST_F(InstTest, HugeDynamicOperandsAmount)
540 {
541 auto graph = CreateGraphStartEndBlocks();
542 const size_t COUNT = 1000;
543 auto save_state = graph->CreateInstSaveState();
544
545 for (size_t i = 0; i < COUNT; i++) {
546 save_state->AppendInput(graph->FindOrCreateConstant(i));
547 save_state->SetVirtualRegister(i, VirtualRegister(i, false));
548 }
549
550 for (size_t i = 0; i < COUNT; i++) {
551 auto user = graph->FindOrCreateConstant(i)->GetUsers().begin()->GetInst();
552 ASSERT_EQ(user, save_state);
553 }
554 }
555
TEST_F(InstTest,FloatConstants)556 TEST_F(InstTest, FloatConstants)
557 {
558 auto graph = CreateGraphStartEndBlocks();
559 graph->GetStartBlock()->AddSucc(graph->GetEndBlock());
560 auto positiv_zero_float = graph->FindOrCreateConstant(0.0f);
561 auto negativ_zero_float = graph->FindOrCreateConstant(-0.0f);
562 auto positiv_zero_double = graph->FindOrCreateConstant(0.0);
563 auto negativ_zero_double = graph->FindOrCreateConstant(-0.0);
564
565 ASSERT_NE(positiv_zero_float, negativ_zero_float);
566 ASSERT_NE(positiv_zero_double, negativ_zero_double);
567 }
568
TEST_F(InstTest,Flags)569 TEST_F(InstTest, Flags)
570 {
571 auto initial_mask = inst_flags::GetFlagsMask(Opcode::LoadObject);
572 auto inst = GetGraph()->CreateInstLoadObject();
573 ASSERT_EQ(initial_mask, inst->GetFlagsMask());
574 ASSERT_EQ(inst->GetFlagsMask(), initial_mask);
575 ASSERT_TRUE(inst->IsLoad());
576 inst->SetFlag(inst_flags::ALLOC);
577 ASSERT_EQ(inst->GetFlagsMask(), initial_mask | inst_flags::ALLOC);
578 ASSERT_TRUE(inst->IsAllocation());
579 inst->ClearFlag(inst_flags::LOAD);
580 ASSERT_FALSE(inst->IsLoad());
581 ASSERT_EQ(inst->GetFlagsMask(), (initial_mask | inst_flags::ALLOC) & ~inst_flags::LOAD);
582 }
583
TEST_F(InstTest,IntrinsicFlags)584 TEST_F(InstTest, IntrinsicFlags)
585 {
586 ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
587 #include "intrinsic_flags_test.inl"
588 }
589
590 } // namespace panda::compiler
591