1 //===- IRSimilarityIdentifierTest.cpp - IRSimilarityIdentifier unit tests -===//
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
7 //===----------------------------------------------------------------------===//
9 // Tests for components for finding similarity such as the instruction mapper,
10 // suffix tree usage, and structural analysis.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Analysis/IRSimilarityIdentifier.h"
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/Allocator.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "gtest/gtest.h"
23 using namespace IRSimilarity
;
25 static std::unique_ptr
<Module
> makeLLVMModule(LLVMContext
&Context
,
26 StringRef ModuleStr
) {
28 std::unique_ptr
<Module
> M
= parseAssemblyString(ModuleStr
, Err
, Context
);
29 assert(M
&& "Bad LLVM IR?");
33 void getVectors(Module
&M
, IRInstructionMapper
&Mapper
,
34 std::vector
<IRInstructionData
*> &InstrList
,
35 std::vector
<unsigned> &UnsignedVec
) {
37 for (BasicBlock
&BB
: F
)
38 Mapper
.convertToUnsignedVec(BB
, InstrList
, UnsignedVec
);
43 std::vector
<std::vector
<IRSimilarityCandidate
>> &SimilarityCandidates
) {
44 // In order to keep the size of the tests from becoming too large, we do not
45 // recognize similarity for branches unless explicitly needed.
46 IRSimilarityIdentifier
Identifier(/*EnableBranchMatching = */false);
47 SimilarityCandidates
= Identifier
.findSimilarity(M
);
50 // Checks that different opcodes are mapped to different values
51 TEST(IRInstructionMapper
, OpcodeDifferentiation
) {
52 StringRef ModuleString
= R
"(
53 define i32 @f(i32 %a, i32 %b) {
60 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
62 std::vector
<IRInstructionData
*> InstrList
;
63 std::vector
<unsigned> UnsignedVec
;
65 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
66 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
67 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
68 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
70 // Check that the size of the unsigned vector and the instruction list are the
71 // same as a safety check.
72 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
74 // Make sure that the unsigned vector is the expected size.
75 ASSERT_TRUE(UnsignedVec
.size() == 3);
77 // Check whether the instructions are not mapped to the same value.
78 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
81 // Checks that the same opcodes and types are mapped to the same values.
82 TEST(IRInstructionMapper
, OpcodeTypeSimilarity
) {
83 StringRef ModuleString
= R
"(
84 define i32 @f(i32 %a, i32 %b) {
91 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
93 std::vector
<IRInstructionData
*> InstrList
;
94 std::vector
<unsigned> UnsignedVec
;
96 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
97 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
98 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
99 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
101 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
102 ASSERT_TRUE(UnsignedVec
.size() == 3);
104 // Check whether the instructions are mapped to the same value.
105 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
108 // Checks that the same opcode and different types are mapped to different
110 TEST(IRInstructionMapper
, TypeDifferentiation
) {
111 StringRef ModuleString
= R
"(
112 define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
119 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
121 std::vector
<IRInstructionData
*> InstrList
;
122 std::vector
<unsigned> UnsignedVec
;
124 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
125 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
126 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
127 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
129 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
130 ASSERT_TRUE(UnsignedVec
.size() == 3);
131 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
134 // Checks that different predicates map to different values.
135 TEST(IRInstructionMapper
, PredicateDifferentiation
) {
136 StringRef ModuleString
= R
"(
137 define i32 @f(i32 %a, i32 %b) {
139 %0 = icmp sge i32 %b, %a
140 %1 = icmp slt i32 %a, %b
144 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
146 std::vector
<IRInstructionData
*> InstrList
;
147 std::vector
<unsigned> UnsignedVec
;
149 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
150 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
151 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
152 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
154 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
155 ASSERT_TRUE(UnsignedVec
.size() == 3);
156 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
159 // Checks that predicates where that can be considered the same when the
160 // operands are swapped, i.e. greater than to less than are mapped to the same
162 TEST(IRInstructionMapper
, PredicateIsomorphism
) {
163 StringRef ModuleString
= R
"(
164 define i32 @f(i32 %a, i32 %b) {
166 %0 = icmp sgt i32 %a, %b
167 %1 = icmp slt i32 %b, %a
171 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
173 std::vector
<IRInstructionData
*> InstrList
;
174 std::vector
<unsigned> UnsignedVec
;
176 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
177 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
178 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
179 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
181 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
182 ASSERT_TRUE(UnsignedVec
.size() == 3);
183 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
186 // Checks that the same predicate maps to the same value.
187 TEST(IRInstructionMapper
, PredicateSimilarity
) {
188 StringRef ModuleString
= R
"(
189 define i32 @f(i32 %a, i32 %b) {
191 %0 = icmp slt i32 %a, %b
192 %1 = icmp slt i32 %b, %a
196 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
198 std::vector
<IRInstructionData
*> InstrList
;
199 std::vector
<unsigned> UnsignedVec
;
201 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
202 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
203 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
204 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
206 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
207 ASSERT_TRUE(UnsignedVec
.size() == 3);
208 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
211 // Checks that the same predicate maps to the same value for floating point
213 TEST(IRInstructionMapper
, FPPredicateSimilarity
) {
214 StringRef ModuleString
= R
"(
215 define i32 @f(double %a, double %b) {
217 %0 = fcmp olt double %a, %b
218 %1 = fcmp olt double %b, %a
222 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
224 std::vector
<IRInstructionData
*> InstrList
;
225 std::vector
<unsigned> UnsignedVec
;
227 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
228 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
229 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
230 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
232 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
233 ASSERT_TRUE(UnsignedVec
.size() == 3);
234 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
237 // Checks that the different predicate maps to a different value for floating
239 TEST(IRInstructionMapper
, FPPredicatDifference
) {
240 StringRef ModuleString
= R
"(
241 define i32 @f(double %a, double %b) {
243 %0 = fcmp olt double %a, %b
244 %1 = fcmp oge double %b, %a
248 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
250 std::vector
<IRInstructionData
*> InstrList
;
251 std::vector
<unsigned> UnsignedVec
;
253 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
254 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
255 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
256 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
258 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
259 ASSERT_TRUE(UnsignedVec
.size() == 3);
260 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
263 // Checks that the zexts that have the same type parameters map to the same
265 TEST(IRInstructionMapper
, ZextTypeSimilarity
) {
266 StringRef ModuleString
= R
"(
267 define i32 @f(i32 %a) {
269 %0 = zext i32 %a to i64
270 %1 = zext i32 %a to i64
274 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
276 std::vector
<IRInstructionData
*> InstrList
;
277 std::vector
<unsigned> UnsignedVec
;
279 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
280 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
281 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
282 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
284 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
285 ASSERT_TRUE(UnsignedVec
.size() == 3);
286 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
289 // Checks that the sexts that have the same type parameters map to the same
291 TEST(IRInstructionMapper
, SextTypeSimilarity
) {
292 StringRef ModuleString
= R
"(
293 define i32 @f(i32 %a) {
295 %0 = sext i32 %a to i64
296 %1 = sext i32 %a to i64
300 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
302 std::vector
<IRInstructionData
*> InstrList
;
303 std::vector
<unsigned> UnsignedVec
;
305 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
306 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
307 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
308 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
310 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
311 ASSERT_TRUE(UnsignedVec
.size() == 3);
312 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
315 // Checks that the zexts that have the different type parameters map to the
316 // different unsigned integers.
317 TEST(IRInstructionMapper
, ZextTypeDifference
) {
318 StringRef ModuleString
= R
"(
319 define i32 @f(i32 %a, i8 %b) {
321 %0 = zext i32 %a to i64
322 %1 = zext i8 %b to i32
326 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
328 std::vector
<IRInstructionData
*> InstrList
;
329 std::vector
<unsigned> UnsignedVec
;
331 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
332 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
333 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
334 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
336 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
337 ASSERT_TRUE(UnsignedVec
.size() == 3);
338 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
341 // Checks that the sexts that have the different type parameters map to the
342 // different unsigned integers.
343 TEST(IRInstructionMapper
, SextTypeDifference
) {
344 StringRef ModuleString
= R
"(
345 define i32 @f(i32 %a, i8 %b) {
347 %0 = sext i32 %a to i64
348 %1 = sext i8 %b to i32
352 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
354 std::vector
<IRInstructionData
*> InstrList
;
355 std::vector
<unsigned> UnsignedVec
;
357 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
358 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
359 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
360 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
362 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
363 ASSERT_TRUE(UnsignedVec
.size() == 3);
364 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
367 // Checks that loads that have the same type are mapped to the same unsigned
369 TEST(IRInstructionMapper
, LoadSimilarType
) {
370 StringRef ModuleString
= R
"(
371 define i32 @f(i32* %a, i32* %b) {
373 %0 = load i32, i32* %a
374 %1 = load i32, i32* %b
378 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
380 std::vector
<IRInstructionData
*> InstrList
;
381 std::vector
<unsigned> UnsignedVec
;
383 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
384 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
385 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
386 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
388 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
389 ASSERT_TRUE(UnsignedVec
.size() == 3);
390 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
393 // Checks that loads that have the different types are mapped to
394 // different unsigned integers.
395 TEST(IRInstructionMapper
, LoadDifferentType
) {
396 StringRef ModuleString
= R
"(
397 define i32 @f(i32* %a, i64* %b) {
399 %0 = load i32, i32* %a
400 %1 = load i64, i64* %b
404 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
406 std::vector
<IRInstructionData
*> InstrList
;
407 std::vector
<unsigned> UnsignedVec
;
409 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
410 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
411 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
412 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
414 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
415 ASSERT_TRUE(UnsignedVec
.size() == 3);
416 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
419 // Checks that loads that have the different aligns are mapped to different
420 // unsigned integers.
421 TEST(IRInstructionMapper
, LoadDifferentAlign
) {
422 StringRef ModuleString
= R
"(
423 define i32 @f(i32* %a, i32* %b) {
425 %0 = load i32, i32* %a, align 4
426 %1 = load i32, i32* %b, align 8
430 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
432 std::vector
<IRInstructionData
*> InstrList
;
433 std::vector
<unsigned> UnsignedVec
;
435 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
436 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
437 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
438 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
440 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
441 ASSERT_TRUE(UnsignedVec
.size() == 3);
442 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
445 // Checks that loads that have the different volatile settings are mapped to
446 // different unsigned integers.
447 TEST(IRInstructionMapper
, LoadDifferentVolatile
) {
448 StringRef ModuleString
= R
"(
449 define i32 @f(i32* %a, i32* %b) {
451 %0 = load volatile i32, i32* %a
452 %1 = load i32, i32* %b
456 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
458 std::vector
<IRInstructionData
*> InstrList
;
459 std::vector
<unsigned> UnsignedVec
;
461 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
462 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
463 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
464 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
466 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
467 ASSERT_TRUE(UnsignedVec
.size() == 3);
468 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
471 // Checks that loads that have the same volatile settings are mapped to
472 // different unsigned integers.
473 TEST(IRInstructionMapper
, LoadSameVolatile
) {
474 StringRef ModuleString
= R
"(
475 define i32 @f(i32* %a, i32* %b) {
477 %0 = load volatile i32, i32* %a
478 %1 = load volatile i32, i32* %b
482 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
484 std::vector
<IRInstructionData
*> InstrList
;
485 std::vector
<unsigned> UnsignedVec
;
487 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
488 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
489 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
490 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
492 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
493 ASSERT_TRUE(UnsignedVec
.size() == 3);
494 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
497 // Checks that loads that have the different atomicity settings are mapped to
498 // different unsigned integers.
499 TEST(IRInstructionMapper
, LoadDifferentAtomic
) {
500 StringRef ModuleString
= R
"(
501 define i32 @f(i32* %a, i32* %b) {
503 %0 = load atomic i32, i32* %a unordered, align 4
504 %1 = load atomic i32, i32* %b monotonic, align 4
508 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
510 std::vector
<IRInstructionData
*> InstrList
;
511 std::vector
<unsigned> UnsignedVec
;
513 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
514 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
515 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
516 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
518 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
519 ASSERT_TRUE(UnsignedVec
.size() == 3);
520 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
523 // Checks that loads that have the same atomicity settings are mapped to
524 // different unsigned integers.
525 TEST(IRInstructionMapper
, LoadSameAtomic
) {
526 StringRef ModuleString
= R
"(
527 define i32 @f(i32* %a, i32* %b) {
529 %0 = load atomic i32, i32* %a unordered, align 4
530 %1 = load atomic i32, i32* %b unordered, align 4
534 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
536 std::vector
<IRInstructionData
*> InstrList
;
537 std::vector
<unsigned> UnsignedVec
;
539 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
540 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
541 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
542 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
544 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
545 ASSERT_TRUE(UnsignedVec
.size() == 3);
546 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
549 // Checks that stores that have the same type are mapped to the same unsigned
551 TEST(IRInstructionMapper
, StoreSimilarType
) {
552 StringRef ModuleString
= R
"(
553 define i32 @f(i32* %a, i32* %b) {
560 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
562 std::vector
<IRInstructionData
*> InstrList
;
563 std::vector
<unsigned> UnsignedVec
;
565 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
566 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
567 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
568 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
570 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
571 ASSERT_TRUE(UnsignedVec
.size() == 3);
572 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
575 // Checks that stores that have the different types are mapped to
576 // different unsigned integers.
577 TEST(IRInstructionMapper
, StoreDifferentType
) {
578 StringRef ModuleString
= R
"(
579 define i32 @f(i32* %a, i64* %b) {
586 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
588 std::vector
<IRInstructionData
*> InstrList
;
589 std::vector
<unsigned> UnsignedVec
;
591 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
592 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
593 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
594 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
596 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
597 ASSERT_TRUE(UnsignedVec
.size() == 3);
598 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
601 // Checks that stores that have the different aligns are mapped to different
602 // unsigned integers.
603 TEST(IRInstructionMapper
, StoreDifferentAlign
) {
604 StringRef ModuleString
= R
"(
605 define i32 @f(i32* %a, i32* %b) {
607 store i32 1, i32* %a, align 4
608 store i32 1, i32* %b, align 8
612 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
614 std::vector
<IRInstructionData
*> InstrList
;
615 std::vector
<unsigned> UnsignedVec
;
617 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
618 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
619 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
620 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
622 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
623 ASSERT_TRUE(UnsignedVec
.size() == 3);
624 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
627 // Checks that stores that have the different volatile settings are mapped to
628 // different unsigned integers.
629 TEST(IRInstructionMapper
, StoreDifferentVolatile
) {
630 StringRef ModuleString
= R
"(
631 define i32 @f(i32* %a, i32* %b) {
633 store volatile i32 1, i32* %a
638 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
640 std::vector
<IRInstructionData
*> InstrList
;
641 std::vector
<unsigned> UnsignedVec
;
643 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
644 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
645 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
646 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
648 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
649 ASSERT_TRUE(UnsignedVec
.size() == 3);
650 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
653 // Checks that stores that have the same volatile settings are mapped to
654 // different unsigned integers.
655 TEST(IRInstructionMapper
, StoreSameVolatile
) {
656 StringRef ModuleString
= R
"(
657 define i32 @f(i32* %a, i32* %b) {
659 store volatile i32 1, i32* %a
660 store volatile i32 1, i32* %b
664 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
666 std::vector
<IRInstructionData
*> InstrList
;
667 std::vector
<unsigned> UnsignedVec
;
669 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
670 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
671 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
672 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
674 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
675 ASSERT_TRUE(UnsignedVec
.size() == 3);
676 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
679 // Checks that loads that have the same atomicity settings are mapped to
680 // different unsigned integers.
681 TEST(IRInstructionMapper
, StoreSameAtomic
) {
682 StringRef ModuleString
= R
"(
683 define i32 @f(i32* %a, i32* %b) {
685 store atomic i32 1, i32* %a unordered, align 4
686 store atomic i32 1, i32* %b unordered, align 4
690 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
692 std::vector
<IRInstructionData
*> InstrList
;
693 std::vector
<unsigned> UnsignedVec
;
695 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
696 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
697 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
698 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
700 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
701 ASSERT_TRUE(UnsignedVec
.size() == 3);
702 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
705 // Checks that loads that have the different atomicity settings are mapped to
706 // different unsigned integers.
707 TEST(IRInstructionMapper
, StoreDifferentAtomic
) {
708 StringRef ModuleString
= R
"(
709 define i32 @f(i32* %a, i32* %b) {
711 store atomic i32 1, i32* %a unordered, align 4
712 store atomic i32 1, i32* %b monotonic, align 4
716 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
718 std::vector
<IRInstructionData
*> InstrList
;
719 std::vector
<unsigned> UnsignedVec
;
721 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
722 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
723 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
724 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
726 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
727 ASSERT_TRUE(UnsignedVec
.size() == 3);
728 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
731 // Checks that the branch is mapped to legal when the option is set.
732 TEST(IRInstructionMapper
, BranchLegal
) {
733 StringRef ModuleString
= R
"(
734 define i32 @f(i32 %a, i32 %b) {
736 %0 = icmp slt i32 %a, %b
737 br i1 %0, label %bb0, label %bb1
742 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
744 std::vector
<IRInstructionData
*> InstrList
;
745 std::vector
<unsigned> UnsignedVec
;
747 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
748 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
749 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
750 Mapper
.InstClassifier
.EnableBranches
= true;
751 Mapper
.initializeForBBs(*M
);
752 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
754 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
755 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
756 ASSERT_TRUE(UnsignedVec
[1] > UnsignedVec
[0]);
757 ASSERT_TRUE(UnsignedVec
[1] < UnsignedVec
[2]);
760 // Checks that a PHINode is mapped to be legal.
761 TEST(IRInstructionMapper
, PhiLegal
) {
762 StringRef ModuleString
= R
"(
763 define i32 @f(i32 %a, i32 %b) {
765 %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
772 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
774 std::vector
<IRInstructionData
*> InstrList
;
775 std::vector
<unsigned> UnsignedVec
;
777 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
778 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
779 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
780 Mapper
.InstClassifier
.EnableBranches
= true;
781 Mapper
.initializeForBBs(*M
);
782 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
784 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
785 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
788 // Checks that a PHINode is mapped to be legal.
789 TEST(IRInstructionMapper
, PhiIllegal
) {
790 StringRef ModuleString
= R
"(
791 define i32 @f(i32 %a, i32 %b) {
793 %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
800 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
802 std::vector
<IRInstructionData
*> InstrList
;
803 std::vector
<unsigned> UnsignedVec
;
805 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
806 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
807 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
808 Mapper
.initializeForBBs(*M
);
809 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
811 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
812 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
813 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
816 // In most cases, the illegal instructions we are collecting don't require any
817 // sort of setup. In these cases, we can just only have illegal instructions,
818 // and the mapper will create 0 length vectors, and we can check that.
820 // In cases where we have legal instructions needed to set up the illegal
821 // instruction, to check illegal instructions are assigned unsigned integers
822 // from the maximum value decreasing to 0, it will be greater than a legal
823 // instruction that comes after. So to check that we have an illegal
824 // instruction, we place a legal instruction after an illegal instruction, and
825 // check that the illegal unsigned integer is greater than the unsigned integer
826 // of the legal instruction.
828 // Checks that an alloca instruction is mapped to be illegal.
829 TEST(IRInstructionMapper
, AllocaIllegal
) {
830 StringRef ModuleString
= R
"(
831 define i32 @f(i32 %a, i32 %b) {
837 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
839 std::vector
<IRInstructionData
*> InstrList
;
840 std::vector
<unsigned> UnsignedVec
;
842 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
843 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
844 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
845 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
847 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
848 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
849 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
852 // Checks that an getelementptr instruction is mapped to be legal. And that
853 // the operands in getelementpointer instructions are the exact same after the
854 // first element operand, which only requires the same type.
855 TEST(IRInstructionMapper
, GetElementPtrSameEndOperands
) {
856 StringRef ModuleString
= R
"(
857 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
858 %struct.ST = type { i32, double, %struct.RT }
859 define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
861 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
862 %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 0
866 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
868 std::vector
<IRInstructionData
*> InstrList
;
869 std::vector
<unsigned> UnsignedVec
;
871 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
872 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
873 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
874 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
876 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
877 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
878 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
881 // Check that when the operands in getelementpointer instructions are not the
882 // exact same after the first element operand, the instructions are mapped to
884 TEST(IRInstructionMapper
, GetElementPtrDifferentEndOperands
) {
885 StringRef ModuleString
= R
"(
886 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
887 %struct.ST = type { i32, double, %struct.RT }
888 define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
890 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
891 %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 2
895 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
897 std::vector
<IRInstructionData
*> InstrList
;
898 std::vector
<unsigned> UnsignedVec
;
900 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
901 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
902 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
903 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
905 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
906 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
907 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
910 // Check that when the operands in getelementpointer instructions are not the
911 // same initial base type, each instruction is mapped to a different value.
912 TEST(IRInstructionMapper
, GetElementPtrDifferentBaseType
) {
913 StringRef ModuleString
= R
"(
914 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
915 %struct.ST = type { i32, double, %struct.RT }
916 define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
918 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a
919 %1 = getelementptr inbounds %struct.RT, %struct.RT* %r, i64 %b
923 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
925 std::vector
<IRInstructionData
*> InstrList
;
926 std::vector
<unsigned> UnsignedVec
;
928 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
929 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
930 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
931 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
933 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
934 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
935 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
938 // Check that when the operands in getelementpointer instructions do not have
939 // the same inbounds modifier, they are not counted as the same.
940 TEST(IRInstructionMapper
, GetElementPtrDifferentInBounds
) {
941 StringRef ModuleString
= R
"(
942 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
943 %struct.ST = type { i32, double, %struct.RT }
944 define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
946 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
947 %1 = getelementptr %struct.ST, %struct.ST* %s, i64 %b, i32 0
951 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
953 std::vector
<IRInstructionData
*> InstrList
;
954 std::vector
<unsigned> UnsignedVec
;
956 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
957 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
958 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
959 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
961 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
962 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
963 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
966 // Checks that indirect call instructions are mapped to be illegal when it is
967 // specified to disallow them.
968 TEST(IRInstructionMapper
, CallsIllegalIndirect
) {
969 StringRef ModuleString
= R
"(
970 define i32 @f(void()* %func) {
976 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
978 std::vector
<IRInstructionData
*> InstrList
;
979 std::vector
<unsigned> UnsignedVec
;
981 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
982 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
983 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
984 Mapper
.InstClassifier
.EnableIndirectCalls
= false;
985 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
987 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
988 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
989 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
992 // Checks that indirect call instructions are mapped to be legal when it is not
993 // specified to disallow them.
994 TEST(IRInstructionMapper
, CallsLegalIndirect
) {
995 StringRef ModuleString
= R
"(
996 define i32 @f(void()* %func) {
1002 LLVMContext Context
;
1003 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1005 std::vector
<IRInstructionData
*> InstrList
;
1006 std::vector
<unsigned> UnsignedVec
;
1008 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1009 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1010 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1011 Mapper
.InstClassifier
.EnableIndirectCalls
= true;
1012 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1014 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1015 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1018 // Checks that a call instruction is mapped to be legal. Here we check that
1019 // a call with the same name, and same types are mapped to the same
1021 TEST(IRInstructionMapper
, CallsSameTypeSameName
) {
1022 StringRef ModuleString
= R
"(
1023 declare i32 @f1(i32, i32)
1024 define i32 @f(i32 %a, i32 %b) {
1026 %0 = call i32 @f1(i32 %a, i32 %b)
1027 %1 = call i32 @f1(i32 %a, i32 %b)
1030 LLVMContext Context
;
1031 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1033 std::vector
<IRInstructionData
*> InstrList
;
1034 std::vector
<unsigned> UnsignedVec
;
1036 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1037 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1038 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1039 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1041 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1042 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1043 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1046 // Here we check that a calls with different names, but the same arguments types
1047 // are mapped to different value when specified that the name must match.
1048 TEST(IRInstructionMapper
, CallsSameArgTypeDifferentNameDisallowed
) {
1049 StringRef ModuleString
= R
"(
1050 declare i32 @f1(i32, i32)
1051 declare i32 @f2(i32, i32)
1052 define i32 @f(i32 %a, i32 %b) {
1054 %0 = call i32 @f1(i32 %a, i32 %b)
1055 %1 = call i32 @f2(i32 %a, i32 %b)
1058 LLVMContext Context
;
1059 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1061 std::vector
<IRInstructionData
*> InstrList
;
1062 std::vector
<unsigned> UnsignedVec
;
1064 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1065 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1066 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1067 Mapper
.EnableMatchCallsByName
= true;
1068 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1070 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1071 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1072 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1075 // Here we check that a calls with different names, but the same arguments types
1076 // are mapped to the same value when it is not specifed that they must match.
1077 TEST(IRInstructionMapper
, CallsSameArgTypeDifferentName
) {
1078 StringRef ModuleString
= R
"(
1079 declare i32 @f1(i32, i32)
1080 declare i32 @f2(i32, i32)
1081 define i32 @f(i32 %a, i32 %b) {
1083 %0 = call i32 @f1(i32 %a, i32 %b)
1084 %1 = call i32 @f2(i32 %a, i32 %b)
1087 LLVMContext Context
;
1088 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1090 std::vector
<IRInstructionData
*> InstrList
;
1091 std::vector
<unsigned> UnsignedVec
;
1093 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1094 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1095 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1096 Mapper
.EnableMatchCallsByName
= false;
1097 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1099 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1100 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1101 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1104 // Here we check that a calls with different names, and different arguments
1105 // types are mapped to different value.
1106 TEST(IRInstructionMapper
, CallsDifferentArgTypeDifferentName
) {
1107 StringRef ModuleString
= R
"(
1108 declare i32 @f1(i32, i32)
1109 declare i32 @f2(i32)
1110 define i32 @f(i32 %a, i32 %b) {
1112 %0 = call i32 @f1(i32 %a, i32 %b)
1113 %1 = call i32 @f2(i32 %a)
1116 LLVMContext Context
;
1117 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1119 std::vector
<IRInstructionData
*> InstrList
;
1120 std::vector
<unsigned> UnsignedVec
;
1122 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1123 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1124 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1125 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1127 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1128 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1129 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1132 // Here we check that calls with different names, and different return
1133 // types are mapped to different value.
1134 TEST(IRInstructionMapper
, CallsDifferentReturnTypeDifferentName
) {
1135 StringRef ModuleString
= R
"(
1136 declare i64 @f1(i32, i32)
1137 declare i32 @f2(i32, i32)
1138 define i32 @f(i32 %a, i32 %b) {
1140 %0 = call i64 @f1(i32 %a, i32 %b)
1141 %1 = call i32 @f2(i32 %a, i32 %b)
1144 LLVMContext Context
;
1145 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1147 std::vector
<IRInstructionData
*> InstrList
;
1148 std::vector
<unsigned> UnsignedVec
;
1150 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1151 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1152 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1153 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1155 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1156 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1157 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1160 // Here we check that calls with the same name, types, and parameters map to the
1161 // same unsigned integer.
1162 TEST(IRInstructionMapper
, CallsSameParameters
) {
1163 StringRef ModuleString
= R
"(
1164 declare i32 @f1(i32, i32)
1165 define i32 @f(i32 %a, i32 %b) {
1167 %0 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1168 %1 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1171 LLVMContext Context
;
1172 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1174 std::vector
<IRInstructionData
*> InstrList
;
1175 std::vector
<unsigned> UnsignedVec
;
1177 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1178 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1179 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1180 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1182 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1183 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1184 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1187 // Here we check that calls with different tail call settings are mapped to
1188 // different values.
1189 TEST(IRInstructionMapper
, CallsDifferentTails
) {
1190 StringRef ModuleString
= R
"(
1191 declare i32 @f1(i32, i32)
1192 define i32 @f(i32 %a, i32 %b) {
1194 %0 = tail call i32 @f1(i32 %a, i32 %b)
1195 %1 = call i32 @f1(i32 %a, i32 %b)
1198 LLVMContext Context
;
1199 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1201 std::vector
<IRInstructionData
*> InstrList
;
1202 std::vector
<unsigned> UnsignedVec
;
1204 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1205 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1206 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1207 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1209 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1210 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1211 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1214 // Here we check that calls with different calling convention settings are
1215 // mapped to different values.
1216 TEST(IRInstructionMapper
, CallsDifferentCallingConventions
) {
1217 StringRef ModuleString
= R
"(
1218 declare i32 @f1(i32, i32)
1219 define i32 @f(i32 %a, i32 %b) {
1221 %0 = call fastcc i32 @f1(i32 %a, i32 %b)
1222 %1 = call i32 @f1(i32 %a, i32 %b)
1225 LLVMContext Context
;
1226 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1228 std::vector
<IRInstructionData
*> InstrList
;
1229 std::vector
<unsigned> UnsignedVec
;
1231 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1232 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1233 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1234 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1236 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1237 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1238 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1241 // Checks that an invoke instruction is mapped to be illegal. Invoke
1242 // instructions are considered to be illegal because of the change in the
1243 // control flow that is currently not recognized.
1244 TEST(IRInstructionMapper
, InvokeIllegal
) {
1245 StringRef ModuleString
= R
"(
1246 define i32 @f(i8 *%gep1, i32 %b) {
1248 invoke i32 undef(i8* undef)
1249 to label %invoke unwind label %lpad
1255 landingpad { i8*, i32 }
1259 LLVMContext Context
;
1260 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1262 std::vector
<IRInstructionData
*> InstrList
;
1263 std::vector
<unsigned> UnsignedVec
;
1265 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1266 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1267 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1268 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1270 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1271 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1272 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1275 // Checks that an callbr instructions are considered to be illegal. Callbr
1276 // instructions are considered to be illegal because of the change in the
1277 // control flow that is currently not recognized.
1278 TEST(IRInstructionMapper
, CallBrInstIllegal
) {
1279 StringRef ModuleString
= R
"(
1280 define void @test() {
1285 define i32 @f(i32 %a, i32 %b) {
1287 callbr void asm "xorl $
0, $
0; jmp $
{1:l
}", "r
,X
,~{dirflag
},~{fpsr
},~{flags
}"(i32 %a, i8* blockaddress(@test, %fail)) to label %normal [label %fail]
1293 LLVMContext Context
;
1294 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1296 std::vector
<IRInstructionData
*> InstrList
;
1297 std::vector
<unsigned> UnsignedVec
;
1299 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1300 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1301 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1302 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1304 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1305 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1306 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1309 // Checks that an debuginfo intrinsics are mapped to be invisible. Since they
1310 // do not semantically change the program, they can be recognized as similar.
1311 TEST(IRInstructionMapper
, DebugInfoInvisible
) {
1312 StringRef ModuleString
= R
"(
1313 define i32 @f(i32 %a, i32 %b) {
1316 call void @llvm.dbg.value(metadata !0)
1321 declare void @llvm.dbg.value(metadata)
1322 !0 = distinct !{!"test\
00", i32 10})";
1323 LLVMContext Context
;
1324 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1326 std::vector
<IRInstructionData
*> InstrList
;
1327 std::vector
<unsigned> UnsignedVec
;
1329 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1330 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1331 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1332 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1334 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1335 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1338 // The following are all exception handling intrinsics. We do not currently
1339 // handle these instruction because they are very context dependent.
1341 // Checks that an eh.typeid.for intrinsic is mapped to be illegal.
1342 TEST(IRInstructionMapper
, ExceptionHandlingTypeIdIllegal
) {
1343 StringRef ModuleString
= R
"(
1344 @_ZTIi = external constant i8*
1347 %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
1351 declare i32 @llvm.eh.typeid.for(i8*))";
1352 LLVMContext Context
;
1353 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1355 std::vector
<IRInstructionData
*> InstrList
;
1356 std::vector
<unsigned> UnsignedVec
;
1358 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1359 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1360 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1361 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1363 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1364 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1365 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1368 // Checks that an eh.exceptioncode intrinsic is mapped to be illegal.
1369 TEST(IRInstructionMapper
, ExceptionHandlingExceptionCodeIllegal
) {
1370 StringRef ModuleString
= R
"(
1371 define i32 @f(i32 %a, i32 %b) {
1373 %0 = catchswitch within none [label %__except] unwind to caller
1376 %1 = catchpad within %0 [i8* null]
1377 catchret from %1 to label %__except
1380 %2 = call i32 @llvm.eh.exceptioncode(token %1)
1384 declare i32 @llvm.eh.exceptioncode(token))";
1385 LLVMContext Context
;
1386 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1388 std::vector
<IRInstructionData
*> InstrList
;
1389 std::vector
<unsigned> UnsignedVec
;
1391 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1392 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1393 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1394 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1396 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1397 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1398 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1401 // Checks that an eh.unwind intrinsic is mapped to be illegal.
1402 TEST(IRInstructionMapper
, ExceptionHandlingUnwindIllegal
) {
1403 StringRef ModuleString
= R
"(
1404 define i32 @f(i32 %a, i32 %b) {
1406 call void @llvm.eh.unwind.init()
1410 declare void @llvm.eh.unwind.init())";
1411 LLVMContext Context
;
1412 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1414 std::vector
<IRInstructionData
*> InstrList
;
1415 std::vector
<unsigned> UnsignedVec
;
1417 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1418 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1419 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1420 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1422 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1423 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1424 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1427 // Checks that an eh.exceptionpointer intrinsic is mapped to be illegal.
1428 TEST(IRInstructionMapper
, ExceptionHandlingExceptionPointerIllegal
) {
1429 StringRef ModuleString
= R
"(
1430 define i32 @f(i32 %a, i32 %b) {
1432 %0 = call i8* @llvm.eh.exceptionpointer.p0i8(i32 0)
1436 declare i8* @llvm.eh.exceptionpointer.p0i8(i32))";
1437 LLVMContext Context
;
1438 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1440 std::vector
<IRInstructionData
*> InstrList
;
1441 std::vector
<unsigned> UnsignedVec
;
1443 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1444 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1445 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1446 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1448 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1449 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1450 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1453 // Checks that a catchpad instruction is mapped to an illegal value.
1454 TEST(IRInstructionMapper
, CatchpadIllegal
) {
1455 StringRef ModuleString
= R
"(
1456 declare void @llvm.donothing() nounwind readnone
1458 define void @function() personality i8 3 {
1460 invoke void @llvm.donothing() to label %normal unwind label %exception
1462 %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1464 catchpad within %cs1 []
1469 LLVMContext Context
;
1470 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1472 std::vector
<IRInstructionData
*> InstrList
;
1473 std::vector
<unsigned> UnsignedVec
;
1475 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1476 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1477 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1478 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1480 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1481 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1482 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1485 // Checks that a cleanuppad instruction is mapped to an illegal value.
1486 TEST(IRInstructionMapper
, CleanuppadIllegal
) {
1487 StringRef ModuleString
= R
"(
1488 declare void @llvm.donothing() nounwind readnone
1490 define void @function() personality i8 3 {
1492 invoke void @llvm.donothing() to label %normal unwind label %exception
1494 %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1496 %clean = cleanuppad within none []
1501 LLVMContext Context
;
1502 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1504 std::vector
<IRInstructionData
*> InstrList
;
1505 std::vector
<unsigned> UnsignedVec
;
1507 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1508 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1509 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1510 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1512 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1513 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1514 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1517 // The following three instructions are memory transfer and setting based, which
1518 // are considered illegal since is extra checking needed to handle the address
1521 // Checks that a memset instruction is mapped to an illegal value when
1523 TEST(IRInstructionMapper
, MemSetIllegal
) {
1524 StringRef ModuleString
= R
"(
1525 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1527 define i64 @function(i64 %x, i64 %z, i64 %n) {
1529 %pool = alloca [59 x i64], align 4
1530 %tmp = bitcast [59 x i64]* %pool to i8*
1531 call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1532 %cmp3 = icmp eq i64 %n, 0
1537 LLVMContext Context
;
1538 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1540 std::vector
<IRInstructionData
*> InstrList
;
1541 std::vector
<unsigned> UnsignedVec
;
1543 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1544 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1545 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1546 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1547 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1549 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1550 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1551 ASSERT_TRUE(UnsignedVec
[2] < UnsignedVec
[0]);
1554 // Checks that a memcpy instruction is mapped to an illegal value when
1556 TEST(IRInstructionMapper
, MemCpyIllegal
) {
1557 StringRef ModuleString
= R
"(
1558 declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1560 define i64 @function(i64 %x, i64 %z, i64 %n) {
1562 %pool = alloca [59 x i64], align 4
1563 %tmp = bitcast [59 x i64]* %pool to i8*
1564 call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1565 %cmp3 = icmp eq i64 %n, 0
1570 LLVMContext Context
;
1571 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1573 std::vector
<IRInstructionData
*> InstrList
;
1574 std::vector
<unsigned> UnsignedVec
;
1576 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1577 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1578 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1579 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1580 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1582 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1583 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1584 ASSERT_GT(UnsignedVec
[2], UnsignedVec
[3]);
1585 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[0]);
1588 // Checks that a memmove instruction is mapped to an illegal value when
1590 TEST(IRInstructionMapper
, MemMoveIllegal
) {
1591 StringRef ModuleString
= R
"(
1592 declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1594 define i64 @function(i64 %x, i64 %z, i64 %n) {
1596 %pool = alloca [59 x i64], align 4
1597 %tmp = bitcast [59 x i64]* %pool to i8*
1598 call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1599 %cmp3 = icmp eq i64 %n, 0
1604 LLVMContext Context
;
1605 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1607 std::vector
<IRInstructionData
*> InstrList
;
1608 std::vector
<unsigned> UnsignedVec
;
1610 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1611 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1612 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1613 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1614 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1616 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1617 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1618 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[0]);
1621 // Checks that mem* instructions are mapped to an legal value when not
1622 // specified, and that all the intrinsics are marked differently.
1623 TEST(IRInstructionMapper
, MemOpsLegal
) {
1624 StringRef ModuleString
= R
"(
1625 declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1626 declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1627 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1629 define i64 @function(i64 %x, i64 %z, i64 %n) {
1631 %pool = alloca [59 x i64], align 4
1632 %tmp = bitcast [59 x i64]* %pool to i8*
1633 call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1634 call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1635 call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1636 %cmp3 = icmp eq i64 %n, 0
1641 LLVMContext Context
;
1642 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1644 std::vector
<IRInstructionData
*> InstrList
;
1645 std::vector
<unsigned> UnsignedVec
;
1647 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1648 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1649 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1650 Mapper
.InstClassifier
.EnableIntrinsics
= true;
1651 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1653 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1654 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(9));
1655 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[3]);
1656 ASSERT_LT(UnsignedVec
[3], UnsignedVec
[4]);
1657 ASSERT_LT(UnsignedVec
[4], UnsignedVec
[5]);
1660 // Checks that a variable argument instructions are mapped to an illegal value.
1661 // We exclude variable argument instructions since variable arguments
1662 // requires extra checking of the argument list.
1663 TEST(IRInstructionMapper
, VarArgsIllegal
) {
1664 StringRef ModuleString
= R
"(
1665 declare void @llvm.va_start(i8*)
1666 declare void @llvm.va_copy(i8*, i8*)
1667 declare void @llvm.va_end(i8*)
1669 define i32 @func1(i32 %a, double %b, i8* %v, ...) nounwind {
1671 %a.addr = alloca i32, align 4
1672 %b.addr = alloca double, align 8
1673 %ap = alloca i8*, align 4
1674 %c = alloca i32, align 4
1675 store i32 %a, i32* %a.addr, align 4
1676 store double %b, double* %b.addr, align 8
1677 %ap1 = bitcast i8** %ap to i8*
1678 call void @llvm.va_start(i8* %ap1)
1679 store double %b, double* %b.addr, align 8
1680 store double %b, double* %b.addr, align 8
1681 %0 = va_arg i8** %ap, i32
1682 store double %b, double* %b.addr, align 8
1683 store double %b, double* %b.addr, align 8
1684 call void @llvm.va_copy(i8* %v, i8* %ap1)
1685 store double %b, double* %b.addr, align 8
1686 store double %b, double* %b.addr, align 8
1687 call void @llvm.va_end(i8* %ap1)
1688 store i32 %0, i32* %c, align 4
1689 %tmp = load i32, i32* %c, align 4
1692 LLVMContext Context
;
1693 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1695 std::vector
<IRInstructionData
*> InstrList
;
1696 std::vector
<unsigned> UnsignedVec
;
1698 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1699 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1700 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1701 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1702 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1704 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1705 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(17));
1706 ASSERT_TRUE(UnsignedVec
[7] < UnsignedVec
[0]);
1707 ASSERT_TRUE(UnsignedVec
[13] < UnsignedVec
[10]);
1708 ASSERT_TRUE(UnsignedVec
[16] < UnsignedVec
[13]);
1711 // Check the length of adding two illegal instructions one after th other. We
1712 // should find that only one element is added for each illegal range.
1713 TEST(IRInstructionMapper
, RepeatedIllegalLength
) {
1714 StringRef ModuleString
= R
"(
1715 define i32 @f(i32 %a, i32 %b) {
1725 LLVMContext Context
;
1726 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1728 std::vector
<IRInstructionData
*> InstrList
;
1729 std::vector
<unsigned> UnsignedVec
;
1731 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1732 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1733 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1734 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1736 // Check that the size of the unsigned vector and the instruction list are the
1737 // same as a safety check.
1738 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1740 // Make sure that the unsigned vector is the expected size.
1741 ASSERT_TRUE(UnsignedVec
.size() == 6);
1744 // A helper function that accepts an instruction list from a module made up of
1745 // two blocks of two legal instructions and terminator, and checks them for
1746 // instruction similarity.
1747 static bool longSimCandCompare(std::vector
<IRInstructionData
*> &InstrList
,
1748 bool Structure
= false, unsigned Length
= 2,
1749 unsigned StartIdxOne
= 0,
1750 unsigned StartIdxTwo
= 3) {
1751 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1753 Start
= InstrList
.begin();
1754 End
= InstrList
.begin();
1756 std::advance(End
, StartIdxOne
+ Length
- 1);
1757 IRSimilarityCandidate
Cand1(StartIdxOne
, Length
, *Start
, *End
);
1759 Start
= InstrList
.begin();
1760 End
= InstrList
.begin();
1762 std::advance(Start
, StartIdxTwo
);
1763 std::advance(End
, StartIdxTwo
+ Length
- 1);
1764 IRSimilarityCandidate
Cand2(StartIdxTwo
, Length
, *Start
, *End
);
1766 return IRSimilarityCandidate::compareStructure(Cand1
, Cand2
);
1767 return IRSimilarityCandidate::isSimilar(Cand1
, Cand2
);
1770 // Checks that two adds with commuted operands are considered to be the same
1772 TEST(IRSimilarityCandidate
, CheckIdenticalInstructions
) {
1773 StringRef ModuleString
= R
"(
1774 define i32 @f(i32 %a, i32 %b) {
1780 LLVMContext Context
;
1781 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1783 std::vector
<IRInstructionData
*> InstrList
;
1784 std::vector
<unsigned> UnsignedVec
;
1786 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1787 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1788 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1789 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1791 // Check to make sure that we have a long enough region.
1792 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(3));
1793 // Check that the instructions were added correctly to both vectors.
1794 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1796 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1797 Start
= InstrList
.begin();
1798 End
= InstrList
.begin();
1799 std::advance(End
, 1);
1800 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
1801 IRSimilarityCandidate
Cand2(0, 2, *Start
, *End
);
1803 ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
1806 // Checks that comparison instructions are found to be similar instructions
1807 // when the operands are flipped and the predicate is also swapped.
1808 TEST(IRSimilarityCandidate
, PredicateIsomorphism
) {
1809 StringRef ModuleString
= R
"(
1810 define i32 @f(i32 %a, i32 %b) {
1812 %0 = icmp sgt i32 %a, %b
1816 %2 = icmp slt i32 %a, %b
1820 LLVMContext Context
;
1821 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1823 std::vector
<IRInstructionData
*> InstrList
;
1824 std::vector
<unsigned> UnsignedVec
;
1826 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1827 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1828 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1829 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1831 ASSERT_TRUE(InstrList
.size() > 5);
1832 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1834 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1835 Start
= InstrList
.begin();
1836 End
= InstrList
.begin();
1838 std::advance(End
, 1);
1839 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
1841 Start
= InstrList
.begin();
1842 End
= InstrList
.begin();
1844 std::advance(Start
, 3);
1845 std::advance(End
, 4);
1846 IRSimilarityCandidate
Cand2(3, 2, *Start
, *End
);
1848 ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
1851 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1852 // are able to differentiate between instructions that have different opcodes.
1853 TEST(IRSimilarityCandidate
, CheckRegionsDifferentInstruction
) {
1854 StringRef ModuleString
= R
"(
1855 define i32 @f(i32 %a, i32 %b) {
1865 LLVMContext Context
;
1866 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1868 std::vector
<IRInstructionData
*> InstrList
;
1869 std::vector
<unsigned> UnsignedVec
;
1871 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1872 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1873 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1874 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1876 // Check to make sure that we have a long enough region.
1877 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1878 // Check that the instructions were added correctly to both vectors.
1879 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1881 ASSERT_FALSE(longSimCandCompare(InstrList
));
1884 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1885 // are able to differentiate between instructions that have different types.
1886 TEST(IRSimilarityCandidate
, CheckRegionsDifferentTypes
) {
1887 StringRef ModuleString
= R
"(
1888 define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
1898 LLVMContext Context
;
1899 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1901 std::vector
<IRInstructionData
*> InstrList
;
1902 std::vector
<unsigned> UnsignedVec
;
1904 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1905 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1906 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1907 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1909 // Check to make sure that we have a long enough region.
1910 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1911 // Check that the instructions were added correctly to both vectors.
1912 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1914 ASSERT_FALSE(longSimCandCompare(InstrList
));
1917 // Check that debug instructions do not impact similarity. They are marked as
1919 TEST(IRSimilarityCandidate
, IdenticalWithDebug
) {
1920 StringRef ModuleString
= R
"(
1921 define i32 @f(i32 %a, i32 %b) {
1924 call void @llvm.dbg.value(metadata !0)
1929 call void @llvm.dbg.value(metadata !1)
1938 declare void @llvm.dbg.value(metadata)
1939 !0 = distinct !{!"test\
00", i32 10}
1940 !1 = distinct !{!"test\
00", i32 11})";
1941 LLVMContext Context
;
1942 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1944 std::vector
<IRInstructionData
*> InstrList
;
1945 std::vector
<unsigned> UnsignedVec
;
1947 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1948 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1949 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1950 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1952 // Check to make sure that we have a long enough region.
1953 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(9));
1954 // Check that the instructions were added correctly to both vectors.
1955 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1957 ASSERT_TRUE(longSimCandCompare(InstrList
));
1960 // Checks that IRSimilarityCandidates that include illegal instructions, are not
1961 // considered to be the same set of instructions. In these sets of instructions
1962 // the allocas are illegal.
1963 TEST(IRSimilarityCandidate
, IllegalInCandidate
) {
1964 StringRef ModuleString
= R
"(
1965 define i32 @f(i32 %a, i32 %b) {
1977 LLVMContext Context
;
1978 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1980 std::vector
<IRInstructionData
*> InstrList
;
1981 std::vector
<unsigned> UnsignedVec
;
1983 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1984 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1985 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1986 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1988 // Check to make sure that we have a long enough region.
1989 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1990 // Check that the instructions were added correctly to both vectors.
1991 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1993 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1995 Start
= InstrList
.begin();
1996 End
= InstrList
.begin();
1998 std::advance(End
, 2);
1999 IRSimilarityCandidate
Cand1(0, 3, *Start
, *End
);
2001 Start
= InstrList
.begin();
2002 End
= InstrList
.begin();
2004 std::advance(Start
, 3);
2005 std::advance(End
, 5);
2006 IRSimilarityCandidate
Cand2(3, 3, *Start
, *End
);
2007 ASSERT_FALSE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
2010 // Checks that different structure, in this case, where we introduce a new
2011 // needed input in one region, is recognized as different.
2012 TEST(IRSimilarityCandidate
, DifferentStructure
) {
2013 StringRef ModuleString
= R
"(
2014 define i32 @f(i32 %a, i32 %b) {
2024 LLVMContext Context
;
2025 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2027 std::vector
<IRInstructionData
*> InstrList
;
2028 std::vector
<unsigned> UnsignedVec
;
2030 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2031 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2032 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2033 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2035 // Check to make sure that we have a long enough region.
2036 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2037 // Check that the instructions were added correctly to both vectors.
2038 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2040 ASSERT_FALSE(longSimCandCompare(InstrList
, true));
2043 // Checks that comparison instructions are found to have the same structure
2044 // when the operands are flipped and the predicate is also swapped.
2045 TEST(IRSimilarityCandidate
, PredicateIsomorphismStructure
) {
2046 StringRef ModuleString
= R
"(
2047 define i32 @f(i32 %a, i32 %b) {
2049 %0 = icmp sgt i32 %a, %b
2053 %2 = icmp slt i32 %b, %a
2057 LLVMContext Context
;
2058 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2060 std::vector
<IRInstructionData
*> InstrList
;
2061 std::vector
<unsigned> UnsignedVec
;
2063 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2064 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2065 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2066 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2068 ASSERT_TRUE(InstrList
.size() > 5);
2069 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2071 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2074 // Checks that different predicates are counted as diferent.
2075 TEST(IRSimilarityCandidate
, PredicateDifference
) {
2076 StringRef ModuleString
= R
"(
2077 define i32 @f(i32 %a, i32 %b) {
2079 %0 = icmp sge i32 %a, %b
2083 %2 = icmp slt i32 %b, %a
2087 LLVMContext Context
;
2088 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2090 std::vector
<IRInstructionData
*> InstrList
;
2091 std::vector
<unsigned> UnsignedVec
;
2093 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2094 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2095 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2096 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2098 ASSERT_TRUE(InstrList
.size() > 5);
2099 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2101 ASSERT_FALSE(longSimCandCompare(InstrList
));
2104 // Checks that the same structure is recognized between two candidates. The
2105 // items %a and %b are used in the same way in both sets of instructions.
2106 TEST(IRSimilarityCandidate
, SameStructure
) {
2107 StringRef ModuleString
= R
"(
2108 define i32 @f(i32 %a, i32 %b) {
2118 LLVMContext Context
;
2119 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2121 std::vector
<IRInstructionData
*> InstrList
;
2122 std::vector
<unsigned> UnsignedVec
;
2124 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2125 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2126 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2127 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2129 // Check to make sure that we have a long enough region.
2130 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2131 // Check that the instructions were added correctly to both vectors.
2132 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2134 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2137 // Checks that the canonical numbering between two candidates matches the found
2138 // mapping between two candidates.
2139 TEST(IRSimilarityCandidate
, CanonicalNumbering
) {
2140 StringRef ModuleString
= R
"(
2141 define i32 @f(i32 %a, i32 %b) {
2151 LLVMContext Context
;
2152 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2154 std::vector
<IRInstructionData
*> InstrList
;
2155 std::vector
<unsigned> UnsignedVec
;
2157 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2158 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2159 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2160 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2162 // Check to make sure that we have a long enough region.
2163 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2164 // Check that the instructions were added correctly to both vectors.
2165 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
2167 std::vector
<IRInstructionData
*>::iterator Start
, End
;
2169 Start
= InstrList
.begin();
2170 End
= InstrList
.begin();
2172 std::advance(End
, 1);
2173 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
2175 Start
= InstrList
.begin();
2176 End
= InstrList
.begin();
2178 std::advance(Start
, 3);
2179 std::advance(End
, 4);
2180 IRSimilarityCandidate
Cand2(3, 2, *Start
, *End
);
2181 DenseMap
<unsigned, DenseSet
<unsigned>> Mapping1
;
2182 DenseMap
<unsigned, DenseSet
<unsigned>> Mapping2
;
2183 ASSERT_TRUE(IRSimilarityCandidate::compareStructure(Cand1
, Cand2
, Mapping1
,
2185 IRSimilarityCandidate::createCanonicalMappingFor(Cand1
);
2186 Cand2
.createCanonicalRelationFrom(Cand1
, Mapping1
, Mapping2
);
2188 for (std::pair
<unsigned, DenseSet
<unsigned>> &P
: Mapping2
) {
2189 unsigned Source
= P
.first
;
2191 ASSERT_TRUE(Cand2
.getCanonicalNum(Source
).has_value());
2192 unsigned Canon
= *Cand2
.getCanonicalNum(Source
);
2193 ASSERT_TRUE(Cand1
.fromCanonicalNum(Canon
).has_value());
2194 unsigned Dest
= *Cand1
.fromCanonicalNum(Canon
);
2196 DenseSet
<unsigned>::iterator It
= P
.second
.find(Dest
);
2197 ASSERT_NE(It
, P
.second
.end());
2201 // Checks that the same structure is recognized between two candidates. While
2202 // the input names are reversed, they still perform the same overall operation.
2203 TEST(IRSimilarityCandidate
, DifferentNameSameStructure
) {
2204 StringRef ModuleString
= R
"(
2205 define i32 @f(i32 %a, i32 %b) {
2215 LLVMContext Context
;
2216 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2218 std::vector
<IRInstructionData
*> InstrList
;
2219 std::vector
<unsigned> UnsignedVec
;
2221 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2222 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2223 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2224 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2226 // Check to make sure that we have a long enough region.
2227 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2228 // Check that the instructions were added correctly to both vectors.
2229 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2231 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2234 // Checks that the same structure is recognized between two candidates when
2235 // the branches target other blocks inside the same region, the relative
2236 // distance between the blocks must be the same.
2237 TEST(IRSimilarityCandidate
, SameBranchStructureInternal
) {
2238 StringRef ModuleString
= R
"(
2239 define i32 @f(i32 %a, i32 %b) {
2250 define i32 @f2(i32 %a, i32 %b) {
2260 LLVMContext Context
;
2261 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2263 std::vector
<IRInstructionData
*> InstrList
;
2264 std::vector
<unsigned> UnsignedVec
;
2266 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2267 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2268 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2269 Mapper
.InstClassifier
.EnableBranches
= true;
2270 Mapper
.initializeForBBs(*M
);
2271 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2273 // Check to make sure that we have a long enough region.
2274 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2275 // Check that the instructions were added correctly to both vectors.
2276 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2278 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 5, 0, 6));
2281 // Checks that the different structure is recognized between two candidates,
2282 // when the branches target other blocks inside the same region, the relative
2283 // distance between the blocks must be the same.
2284 TEST(IRSimilarityCandidate
, DifferentBranchStructureInternal
) {
2285 StringRef ModuleString
= R
"(
2286 define i32 @f(i32 %a, i32 %b) {
2301 define i32 @f2(i32 %a, i32 %b) {
2315 LLVMContext Context
;
2316 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2318 std::vector
<IRInstructionData
*> InstrList
;
2319 std::vector
<unsigned> UnsignedVec
;
2321 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2322 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2323 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2324 Mapper
.InstClassifier
.EnableBranches
= true;
2325 Mapper
.initializeForBBs(*M
);
2326 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2328 // Check to make sure that we have a long enough region.
2329 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(18));
2330 // Check that the instructions were added correctly to both vectors.
2331 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2333 ASSERT_FALSE(longSimCandCompare(InstrList
, true, 6, 0, 9));
2336 // Checks that the same structure is recognized between two candidates, when
2337 // the branches target other blocks outside region, the relative distance
2338 // does not need to be the same.
2339 TEST(IRSimilarityCandidate
, SameBranchStructureOutside
) {
2340 StringRef ModuleString
= R
"(
2341 define i32 @f(i32 %a, i32 %b) {
2352 define i32 @f2(i32 %a, i32 %b) {
2362 LLVMContext Context
;
2363 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2365 std::vector
<IRInstructionData
*> InstrList
;
2366 std::vector
<unsigned> UnsignedVec
;
2368 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2369 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2370 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2371 Mapper
.InstClassifier
.EnableBranches
= true;
2372 Mapper
.initializeForBBs(*M
);
2373 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2375 // Check to make sure that we have a long enough region.
2376 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2377 // Check that the instructions were added correctly to both vectors.
2378 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2380 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 3, 0, 6));
2383 // Checks that the same structure is recognized between two candidates, when
2384 // the branches target other blocks outside region, the relative distance
2385 // does not need to be the same.
2386 TEST(IRSimilarityCandidate
, DifferentBranchStructureOutside
) {
2387 StringRef ModuleString
= R
"(
2388 define i32 @f(i32 %a, i32 %b) {
2399 define i32 @f2(i32 %a, i32 %b) {
2413 LLVMContext Context
;
2414 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2416 std::vector
<IRInstructionData
*> InstrList
;
2417 std::vector
<unsigned> UnsignedVec
;
2419 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2420 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2421 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2422 Mapper
.InstClassifier
.EnableBranches
= true;
2423 Mapper
.initializeForBBs(*M
);
2424 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2426 // Check to make sure that we have a long enough region.
2427 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(15));
2428 // Check that the instructions were added correctly to both vectors.
2429 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2431 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 3, 0, 6));
2434 // Checks that the same structure is recognized between two candidates,
2435 // when the phi predecessor are other blocks inside the same region,
2436 // the relative distance between the blocks must be the same.
2437 TEST(IRSimilarityCandidate
, SamePHIStructureInternal
) {
2438 StringRef ModuleString
= R
"(
2439 define i32 @f(i32 %a, i32 %b) {
2445 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2451 define i32 @f2(i32 %a, i32 %b) {
2457 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2462 LLVMContext Context
;
2463 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2465 std::vector
<IRInstructionData
*> InstrList
;
2466 std::vector
<unsigned> UnsignedVec
;
2468 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2469 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2470 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2471 Mapper
.InstClassifier
.EnableBranches
= true;
2472 Mapper
.initializeForBBs(*M
);
2473 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2475 // Check to make sure that we have a long enough region.
2476 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2477 // Check that the instructions were added correctly to both vectors.
2478 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2480 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 4, 0, 6));
2483 // Checks that the different structure is recognized between two candidates,
2484 // when the phi predecessor are other blocks inside the same region,
2485 // the relative distance between the blocks must be the same.
2486 TEST(IRSimilarityCandidate
, DifferentPHIStructureInternal
) {
2487 StringRef ModuleString
= R
"(
2488 define i32 @f(i32 %a, i32 %b) {
2496 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2502 define i32 @f2(i32 %a, i32 %b) {
2510 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb3 ]
2515 LLVMContext Context
;
2516 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2518 std::vector
<IRInstructionData
*> InstrList
;
2519 std::vector
<unsigned> UnsignedVec
;
2521 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2522 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2523 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2524 Mapper
.InstClassifier
.EnableBranches
= true;
2525 Mapper
.initializeForBBs(*M
);
2526 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2528 // Check to make sure that we have a long enough region.
2529 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(14));
2530 // Check that the instructions were added correctly to both vectors.
2531 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2533 ASSERT_FALSE(longSimCandCompare(InstrList
, true, 5, 0, 7));
2536 // Checks that two sets of identical instructions are found to be the same.
2537 // Both sequences of adds have the same operand ordering, and the same
2538 // instructions, making them strcturally equivalent.
2539 TEST(IRSimilarityIdentifier
, IdentitySimilarity
) {
2540 StringRef ModuleString
= R
"(
2541 define i32 @f(i32 %a, i32 %b) {
2551 LLVMContext Context
;
2552 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2554 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2555 getSimilarities(*M
, SimilarityCandidates
);
2557 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2558 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2559 ASSERT_TRUE(Cands
.size() == 2);
2560 unsigned InstIdx
= 0;
2561 for (IRSimilarityCandidate
&Cand
: Cands
) {
2562 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2568 // Checks that incorrect sequences are not found as similar. In this case,
2569 // we have different sequences of instructions.
2570 TEST(IRSimilarityIdentifier
, InstructionDifference
) {
2571 StringRef ModuleString
= R
"(
2572 define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2582 LLVMContext Context
;
2583 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2585 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2586 getSimilarities(*M
, SimilarityCandidates
);
2588 ASSERT_TRUE(SimilarityCandidates
.empty());
2591 // This test checks to see whether we can detect similarity for commutative
2592 // instructions where the operands have been reversed.
2593 TEST(IRSimilarityIdentifier
, CommutativeSimilarity
) {
2594 StringRef ModuleString
= R
"(
2595 define i32 @f(i32 %a, i32 %b) {
2605 LLVMContext Context
;
2606 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2608 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2609 getSimilarities(*M
, SimilarityCandidates
);
2611 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2612 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2613 ASSERT_TRUE(Cands
.size() == 2);
2614 unsigned InstIdx
= 0;
2615 for (IRSimilarityCandidate
&Cand
: Cands
) {
2616 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2622 // This test ensures that when the first instruction in a sequence is
2623 // a commutative instruction with the same value (mcomm_inst_same_val), but the
2624 // corresponding instruction (comm_inst_diff_val) is not, we mark the regions
2626 TEST(IRSimilarityIdentifier
, CommutativeSameValueFirstMisMatch
) {
2627 StringRef ModuleString
= R
"(
2628 define void @v_1_0(i64 %v_33) {
2630 %comm_inst_same_val = mul i64 undef, undef
2631 %add = add i64 %comm_inst_same_val, %v_33
2632 %comm_inst_diff_val = mul i64 0, undef
2633 %mul.i = add i64 %comm_inst_diff_val, %comm_inst_diff_val
2636 LLVMContext Context
;
2637 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2639 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2640 getSimilarities(*M
, SimilarityCandidates
);
2642 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2645 // This test makes sure that intrinsic functions that are marked commutative
2646 // are still treated as non-commutative since they are function calls.
2647 TEST(IRSimilarityIdentifier
, IntrinsicCommutative
) {
2648 // If treated as commutative, we will fail to find a valid mapping, causing
2649 // an assertion error.
2650 StringRef ModuleString
= R
"(
2651 define void @foo() {
2653 %0 = call i16 @llvm.smul.fix.i16(i16 16384, i16 16384, i32 15)
2654 store i16 %0, i16* undef, align 1
2655 %1 = icmp eq i16 undef, 8192
2657 %2 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 16384, i32 15)
2658 store i16 %2, i16* undef, align 1
2659 %3 = icmp eq i16 undef, -8192
2661 %4 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 -16384, i32 15)
2667 ; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
2668 declare i16 @llvm.smul.fix.i16(i16, i16, i32 immarg))";
2669 LLVMContext Context
;
2670 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2672 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2673 getSimilarities(*M
, SimilarityCandidates
);
2675 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2678 // This test checks to see whether we can detect different structure in
2679 // commutative instructions. In this case, the second operand in the second
2680 // add is different.
2681 TEST(IRSimilarityIdentifier
, NoCommutativeSimilarity
) {
2682 StringRef ModuleString
= R
"(
2683 define i32 @f(i32 %a, i32 %b) {
2693 LLVMContext Context
;
2694 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2696 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2697 getSimilarities(*M
, SimilarityCandidates
);
2699 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2702 // Check that we are not finding similarity in non commutative
2703 // instructions. That is, while the instruction and operands used are the same
2704 // in the two subtraction sequences, they are in a different order, and cannot
2705 // be counted as the same since a subtraction is not commutative.
2706 TEST(IRSimilarityIdentifier
, NonCommutativeDifference
) {
2707 StringRef ModuleString
= R
"(
2708 define i32 @f(i32 %a, i32 %b) {
2718 LLVMContext Context
;
2719 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2721 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2722 getSimilarities(*M
, SimilarityCandidates
);
2724 ASSERT_TRUE(SimilarityCandidates
.empty());
2727 // Check that we find similarity despite changing the register names.
2728 TEST(IRSimilarityIdentifier
, MappingSimilarity
) {
2729 StringRef ModuleString
= R
"(
2730 define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2740 LLVMContext Context
;
2741 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2743 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2744 getSimilarities(*M
, SimilarityCandidates
);
2746 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2747 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2748 ASSERT_TRUE(Cands
.size() == 2);
2749 unsigned InstIdx
= 0;
2750 for (IRSimilarityCandidate
&Cand
: Cands
) {
2751 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2757 // Check that we find instances of swapped predicate isomorphism. That is,
2758 // for predicates that can be flipped, e.g. greater than to less than,
2759 // we can identify that instances of these different literal predicates, but are
2760 // the same within a single swap can be found.
2761 TEST(IRSimilarityIdentifier
, PredicateIsomorphism
) {
2762 StringRef ModuleString
= R
"(
2763 define i32 @f(i32 %a, i32 %b) {
2766 %1 = icmp sgt i32 %b, %a
2770 %3 = icmp slt i32 %a, %b
2773 LLVMContext Context
;
2774 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2776 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2777 getSimilarities(*M
, SimilarityCandidates
);
2779 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2780 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2781 ASSERT_TRUE(Cands
.size() == 2);
2782 unsigned InstIdx
= 0;
2783 for (IRSimilarityCandidate
&Cand
: Cands
) {
2784 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2790 // Checks that constants are detected as the same operand in each use in the
2791 // sequences of instructions. Also checks that we can find structural
2792 // equivalence using constants. In this case the 1 has the same use pattern as
2794 TEST(IRSimilarityIdentifier
, ConstantMappingSimilarity
) {
2795 StringRef ModuleString
= R
"(
2796 define i32 @f(i32 %a, i32 %b) {
2799 %1 = icmp sgt i32 %b, 1
2803 %3 = icmp sgt i32 %b, %a
2806 LLVMContext Context
;
2807 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2809 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2810 getSimilarities(*M
, SimilarityCandidates
);
2812 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2813 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2814 ASSERT_TRUE(Cands
.size() == 2);
2815 unsigned InstIdx
= 0;
2816 for (IRSimilarityCandidate
&Cand
: Cands
) {
2817 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2823 // Check that constants are uniquely identified. i.e. two different constants
2824 // are not considered the same. This means that this should not find any
2825 // structural similarity.
2826 TEST(IRSimilarityIdentifier
, ConstantMappingDifference
) {
2827 StringRef ModuleString
= R
"(
2828 define i32 @f(i32 %a, i32 %b) {
2831 %1 = icmp sgt i32 %b, 2
2835 %3 = icmp slt i32 %a, %b
2838 LLVMContext Context
;
2839 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2841 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2842 getSimilarities(*M
, SimilarityCandidates
);
2844 ASSERT_TRUE(SimilarityCandidates
.empty());