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/ADT/ScopeExit.h"
16 #include "llvm/AsmParser/Parser.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Support/Allocator.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "gtest/gtest.h"
24 using namespace IRSimilarity
;
26 extern llvm::cl::opt
<bool> UseNewDbgInfoFormat
;
27 extern cl::opt
<cl::boolOrDefault
> PreserveInputDbgFormat
;
28 extern bool WriteNewDbgInfoFormatToBitcode
;
29 extern cl::opt
<bool> WriteNewDbgInfoFormat
;
31 static std::unique_ptr
<Module
> makeLLVMModule(LLVMContext
&Context
,
32 StringRef ModuleStr
) {
34 std::unique_ptr
<Module
> M
= parseAssemblyString(ModuleStr
, Err
, Context
);
35 assert(M
&& "Bad LLVM IR?");
39 void getVectors(Module
&M
, IRInstructionMapper
&Mapper
,
40 std::vector
<IRInstructionData
*> &InstrList
,
41 std::vector
<unsigned> &UnsignedVec
) {
43 for (BasicBlock
&BB
: F
)
44 Mapper
.convertToUnsignedVec(BB
, InstrList
, UnsignedVec
);
49 std::vector
<std::vector
<IRSimilarityCandidate
>> &SimilarityCandidates
) {
50 // In order to keep the size of the tests from becoming too large, we do not
51 // recognize similarity for branches unless explicitly needed.
52 IRSimilarityIdentifier
Identifier(/*EnableBranchMatching = */false);
53 SimilarityCandidates
= Identifier
.findSimilarity(M
);
56 // Checks that different opcodes are mapped to different values
57 TEST(IRInstructionMapper
, OpcodeDifferentiation
) {
58 StringRef ModuleString
= R
"(
59 define i32 @f(i32 %a, i32 %b) {
66 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
68 std::vector
<IRInstructionData
*> InstrList
;
69 std::vector
<unsigned> UnsignedVec
;
71 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
72 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
73 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
74 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
76 // Check that the size of the unsigned vector and the instruction list are the
77 // same as a safety check.
78 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
80 // Make sure that the unsigned vector is the expected size.
81 ASSERT_TRUE(UnsignedVec
.size() == 3);
83 // Check whether the instructions are not mapped to the same value.
84 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
87 // Checks that the same opcodes and types are mapped to the same values.
88 TEST(IRInstructionMapper
, OpcodeTypeSimilarity
) {
89 StringRef ModuleString
= R
"(
90 define i32 @f(i32 %a, i32 %b) {
97 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
99 std::vector
<IRInstructionData
*> InstrList
;
100 std::vector
<unsigned> UnsignedVec
;
102 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
103 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
104 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
105 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
107 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
108 ASSERT_TRUE(UnsignedVec
.size() == 3);
110 // Check whether the instructions are mapped to the same value.
111 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
114 // Checks that the same opcode and different types are mapped to different
116 TEST(IRInstructionMapper
, TypeDifferentiation
) {
117 StringRef ModuleString
= R
"(
118 define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
125 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
127 std::vector
<IRInstructionData
*> InstrList
;
128 std::vector
<unsigned> UnsignedVec
;
130 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
131 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
132 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
133 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
135 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
136 ASSERT_TRUE(UnsignedVec
.size() == 3);
137 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
140 // Checks that different predicates map to different values.
141 TEST(IRInstructionMapper
, PredicateDifferentiation
) {
142 StringRef ModuleString
= R
"(
143 define i32 @f(i32 %a, i32 %b) {
145 %0 = icmp sge i32 %b, %a
146 %1 = icmp slt i32 %a, %b
150 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
152 std::vector
<IRInstructionData
*> InstrList
;
153 std::vector
<unsigned> UnsignedVec
;
155 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
156 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
157 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
158 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
160 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
161 ASSERT_TRUE(UnsignedVec
.size() == 3);
162 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
165 // Checks that predicates where that can be considered the same when the
166 // operands are swapped, i.e. greater than to less than are mapped to the same
168 TEST(IRInstructionMapper
, PredicateIsomorphism
) {
169 StringRef ModuleString
= R
"(
170 define i32 @f(i32 %a, i32 %b) {
172 %0 = icmp sgt i32 %a, %b
173 %1 = icmp slt i32 %b, %a
177 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
179 std::vector
<IRInstructionData
*> InstrList
;
180 std::vector
<unsigned> UnsignedVec
;
182 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
183 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
184 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
185 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
187 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
188 ASSERT_TRUE(UnsignedVec
.size() == 3);
189 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
192 // Checks that the same predicate maps to the same value.
193 TEST(IRInstructionMapper
, PredicateSimilarity
) {
194 StringRef ModuleString
= R
"(
195 define i32 @f(i32 %a, i32 %b) {
197 %0 = icmp slt i32 %a, %b
198 %1 = icmp slt i32 %b, %a
202 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
204 std::vector
<IRInstructionData
*> InstrList
;
205 std::vector
<unsigned> UnsignedVec
;
207 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
208 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
209 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
210 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
212 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
213 ASSERT_TRUE(UnsignedVec
.size() == 3);
214 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
217 // Checks that the same predicate maps to the same value for floating point
219 TEST(IRInstructionMapper
, FPPredicateSimilarity
) {
220 StringRef ModuleString
= R
"(
221 define i32 @f(double %a, double %b) {
223 %0 = fcmp olt double %a, %b
224 %1 = fcmp olt double %b, %a
228 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
230 std::vector
<IRInstructionData
*> InstrList
;
231 std::vector
<unsigned> UnsignedVec
;
233 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
234 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
235 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
236 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
238 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
239 ASSERT_TRUE(UnsignedVec
.size() == 3);
240 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
243 // Checks that the different predicate maps to a different value for floating
245 TEST(IRInstructionMapper
, FPPredicatDifference
) {
246 StringRef ModuleString
= R
"(
247 define i32 @f(double %a, double %b) {
249 %0 = fcmp olt double %a, %b
250 %1 = fcmp oge double %b, %a
254 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
256 std::vector
<IRInstructionData
*> InstrList
;
257 std::vector
<unsigned> UnsignedVec
;
259 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
260 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
261 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
262 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
264 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
265 ASSERT_TRUE(UnsignedVec
.size() == 3);
266 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
269 // Checks that the zexts that have the same type parameters map to the same
271 TEST(IRInstructionMapper
, ZextTypeSimilarity
) {
272 StringRef ModuleString
= R
"(
273 define i32 @f(i32 %a) {
275 %0 = zext i32 %a to i64
276 %1 = zext i32 %a to i64
280 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
282 std::vector
<IRInstructionData
*> InstrList
;
283 std::vector
<unsigned> UnsignedVec
;
285 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
286 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
287 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
288 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
290 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
291 ASSERT_TRUE(UnsignedVec
.size() == 3);
292 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
295 // Checks that the sexts that have the same type parameters map to the same
297 TEST(IRInstructionMapper
, SextTypeSimilarity
) {
298 StringRef ModuleString
= R
"(
299 define i32 @f(i32 %a) {
301 %0 = sext i32 %a to i64
302 %1 = sext i32 %a to i64
306 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
308 std::vector
<IRInstructionData
*> InstrList
;
309 std::vector
<unsigned> UnsignedVec
;
311 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
312 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
313 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
314 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
316 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
317 ASSERT_TRUE(UnsignedVec
.size() == 3);
318 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
321 // Checks that the zexts that have the different type parameters map to the
322 // different unsigned integers.
323 TEST(IRInstructionMapper
, ZextTypeDifference
) {
324 StringRef ModuleString
= R
"(
325 define i32 @f(i32 %a, i8 %b) {
327 %0 = zext i32 %a to i64
328 %1 = zext i8 %b to i32
332 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
334 std::vector
<IRInstructionData
*> InstrList
;
335 std::vector
<unsigned> UnsignedVec
;
337 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
338 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
339 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
340 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
342 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
343 ASSERT_TRUE(UnsignedVec
.size() == 3);
344 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
347 // Checks that the sexts that have the different type parameters map to the
348 // different unsigned integers.
349 TEST(IRInstructionMapper
, SextTypeDifference
) {
350 StringRef ModuleString
= R
"(
351 define i32 @f(i32 %a, i8 %b) {
353 %0 = sext i32 %a to i64
354 %1 = sext i8 %b to i32
358 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
360 std::vector
<IRInstructionData
*> InstrList
;
361 std::vector
<unsigned> UnsignedVec
;
363 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
364 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
365 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
366 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
368 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
369 ASSERT_TRUE(UnsignedVec
.size() == 3);
370 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
373 // Checks that loads that have the same type are mapped to the same unsigned
375 TEST(IRInstructionMapper
, LoadSimilarType
) {
376 StringRef ModuleString
= R
"(
377 define i32 @f(i32* %a, i32* %b) {
379 %0 = load i32, i32* %a
380 %1 = load i32, i32* %b
384 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
386 std::vector
<IRInstructionData
*> InstrList
;
387 std::vector
<unsigned> UnsignedVec
;
389 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
390 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
391 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
392 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
394 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
395 ASSERT_TRUE(UnsignedVec
.size() == 3);
396 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
399 // Checks that loads that have the different types are mapped to
400 // different unsigned integers.
401 TEST(IRInstructionMapper
, LoadDifferentType
) {
402 StringRef ModuleString
= R
"(
403 define i32 @f(i32* %a, i64* %b) {
405 %0 = load i32, i32* %a
406 %1 = load i64, i64* %b
410 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
412 std::vector
<IRInstructionData
*> InstrList
;
413 std::vector
<unsigned> UnsignedVec
;
415 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
416 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
417 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
418 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
420 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
421 ASSERT_TRUE(UnsignedVec
.size() == 3);
422 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
425 // Checks that loads that have the different aligns are mapped to different
426 // unsigned integers.
427 TEST(IRInstructionMapper
, LoadDifferentAlign
) {
428 StringRef ModuleString
= R
"(
429 define i32 @f(i32* %a, i32* %b) {
431 %0 = load i32, i32* %a, align 4
432 %1 = load i32, i32* %b, align 8
436 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
438 std::vector
<IRInstructionData
*> InstrList
;
439 std::vector
<unsigned> UnsignedVec
;
441 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
442 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
443 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
444 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
446 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
447 ASSERT_TRUE(UnsignedVec
.size() == 3);
448 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
451 // Checks that loads that have the different volatile settings are mapped to
452 // different unsigned integers.
453 TEST(IRInstructionMapper
, LoadDifferentVolatile
) {
454 StringRef ModuleString
= R
"(
455 define i32 @f(i32* %a, i32* %b) {
457 %0 = load volatile i32, i32* %a
458 %1 = load i32, i32* %b
462 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
464 std::vector
<IRInstructionData
*> InstrList
;
465 std::vector
<unsigned> UnsignedVec
;
467 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
468 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
469 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
470 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
472 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
473 ASSERT_TRUE(UnsignedVec
.size() == 3);
474 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
477 // Checks that loads that have the same volatile settings are mapped to
478 // different unsigned integers.
479 TEST(IRInstructionMapper
, LoadSameVolatile
) {
480 StringRef ModuleString
= R
"(
481 define i32 @f(i32* %a, i32* %b) {
483 %0 = load volatile i32, i32* %a
484 %1 = load volatile i32, i32* %b
488 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
490 std::vector
<IRInstructionData
*> InstrList
;
491 std::vector
<unsigned> UnsignedVec
;
493 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
494 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
495 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
496 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
498 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
499 ASSERT_TRUE(UnsignedVec
.size() == 3);
500 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
503 // Checks that loads that have the different atomicity settings are mapped to
504 // different unsigned integers.
505 TEST(IRInstructionMapper
, LoadDifferentAtomic
) {
506 StringRef ModuleString
= R
"(
507 define i32 @f(i32* %a, i32* %b) {
509 %0 = load atomic i32, i32* %a unordered, align 4
510 %1 = load atomic i32, i32* %b monotonic, align 4
514 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
516 std::vector
<IRInstructionData
*> InstrList
;
517 std::vector
<unsigned> UnsignedVec
;
519 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
520 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
521 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
522 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
524 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
525 ASSERT_TRUE(UnsignedVec
.size() == 3);
526 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
529 // Checks that loads that have the same atomicity settings are mapped to
530 // different unsigned integers.
531 TEST(IRInstructionMapper
, LoadSameAtomic
) {
532 StringRef ModuleString
= R
"(
533 define i32 @f(i32* %a, i32* %b) {
535 %0 = load atomic i32, i32* %a unordered, align 4
536 %1 = load atomic i32, i32* %b unordered, align 4
540 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
542 std::vector
<IRInstructionData
*> InstrList
;
543 std::vector
<unsigned> UnsignedVec
;
545 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
546 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
547 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
548 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
550 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
551 ASSERT_TRUE(UnsignedVec
.size() == 3);
552 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
555 // Checks that stores that have the same type are mapped to the same unsigned
557 TEST(IRInstructionMapper
, StoreSimilarType
) {
558 StringRef ModuleString
= R
"(
559 define i32 @f(i32* %a, i32* %b) {
566 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
568 std::vector
<IRInstructionData
*> InstrList
;
569 std::vector
<unsigned> UnsignedVec
;
571 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
572 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
573 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
574 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
576 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
577 ASSERT_TRUE(UnsignedVec
.size() == 3);
578 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
581 // Checks that stores that have the different types are mapped to
582 // different unsigned integers.
583 TEST(IRInstructionMapper
, StoreDifferentType
) {
584 StringRef ModuleString
= R
"(
585 define i32 @f(i32* %a, i64* %b) {
592 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
594 std::vector
<IRInstructionData
*> InstrList
;
595 std::vector
<unsigned> UnsignedVec
;
597 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
598 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
599 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
600 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
602 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
603 ASSERT_TRUE(UnsignedVec
.size() == 3);
604 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
607 // Checks that stores that have the different aligns are mapped to different
608 // unsigned integers.
609 TEST(IRInstructionMapper
, StoreDifferentAlign
) {
610 StringRef ModuleString
= R
"(
611 define i32 @f(i32* %a, i32* %b) {
613 store i32 1, i32* %a, align 4
614 store i32 1, i32* %b, align 8
618 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
620 std::vector
<IRInstructionData
*> InstrList
;
621 std::vector
<unsigned> UnsignedVec
;
623 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
624 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
625 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
626 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
628 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
629 ASSERT_TRUE(UnsignedVec
.size() == 3);
630 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
633 // Checks that stores that have the different volatile settings are mapped to
634 // different unsigned integers.
635 TEST(IRInstructionMapper
, StoreDifferentVolatile
) {
636 StringRef ModuleString
= R
"(
637 define i32 @f(i32* %a, i32* %b) {
639 store volatile i32 1, i32* %a
644 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
646 std::vector
<IRInstructionData
*> InstrList
;
647 std::vector
<unsigned> UnsignedVec
;
649 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
650 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
651 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
652 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
654 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
655 ASSERT_TRUE(UnsignedVec
.size() == 3);
656 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
659 // Checks that stores that have the same volatile settings are mapped to
660 // different unsigned integers.
661 TEST(IRInstructionMapper
, StoreSameVolatile
) {
662 StringRef ModuleString
= R
"(
663 define i32 @f(i32* %a, i32* %b) {
665 store volatile i32 1, i32* %a
666 store volatile i32 1, i32* %b
670 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
672 std::vector
<IRInstructionData
*> InstrList
;
673 std::vector
<unsigned> UnsignedVec
;
675 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
676 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
677 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
678 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
680 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
681 ASSERT_TRUE(UnsignedVec
.size() == 3);
682 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
685 // Checks that loads that have the same atomicity settings are mapped to
686 // different unsigned integers.
687 TEST(IRInstructionMapper
, StoreSameAtomic
) {
688 StringRef ModuleString
= R
"(
689 define i32 @f(i32* %a, i32* %b) {
691 store atomic i32 1, i32* %a unordered, align 4
692 store atomic i32 1, i32* %b unordered, align 4
696 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
698 std::vector
<IRInstructionData
*> InstrList
;
699 std::vector
<unsigned> UnsignedVec
;
701 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
702 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
703 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
704 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
706 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
707 ASSERT_TRUE(UnsignedVec
.size() == 3);
708 ASSERT_TRUE(UnsignedVec
[0] == UnsignedVec
[1]);
711 // Checks that loads that have the different atomicity settings are mapped to
712 // different unsigned integers.
713 TEST(IRInstructionMapper
, StoreDifferentAtomic
) {
714 StringRef ModuleString
= R
"(
715 define i32 @f(i32* %a, i32* %b) {
717 store atomic i32 1, i32* %a unordered, align 4
718 store atomic i32 1, i32* %b monotonic, align 4
722 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
724 std::vector
<IRInstructionData
*> InstrList
;
725 std::vector
<unsigned> UnsignedVec
;
727 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
728 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
729 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
730 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
732 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
733 ASSERT_TRUE(UnsignedVec
.size() == 3);
734 ASSERT_TRUE(UnsignedVec
[0] != UnsignedVec
[1]);
737 // Checks that the branch is mapped to legal when the option is set.
738 TEST(IRInstructionMapper
, BranchLegal
) {
739 StringRef ModuleString
= R
"(
740 define i32 @f(i32 %a, i32 %b) {
742 %0 = icmp slt i32 %a, %b
743 br i1 %0, label %bb0, label %bb1
748 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
750 std::vector
<IRInstructionData
*> InstrList
;
751 std::vector
<unsigned> UnsignedVec
;
753 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
754 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
755 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
756 Mapper
.InstClassifier
.EnableBranches
= true;
757 Mapper
.initializeForBBs(*M
);
758 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
760 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
761 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
762 ASSERT_TRUE(UnsignedVec
[1] > UnsignedVec
[0]);
763 ASSERT_TRUE(UnsignedVec
[1] < UnsignedVec
[2]);
766 // Checks that a PHINode is mapped to be legal.
767 TEST(IRInstructionMapper
, PhiLegal
) {
768 StringRef ModuleString
= R
"(
769 define i32 @f(i32 %a, i32 %b) {
771 %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
778 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
780 std::vector
<IRInstructionData
*> InstrList
;
781 std::vector
<unsigned> UnsignedVec
;
783 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
784 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
785 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
786 Mapper
.InstClassifier
.EnableBranches
= true;
787 Mapper
.initializeForBBs(*M
);
788 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
790 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
791 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
794 // Checks that a PHINode is mapped to be legal.
795 TEST(IRInstructionMapper
, PhiIllegal
) {
796 StringRef ModuleString
= R
"(
797 define i32 @f(i32 %a, i32 %b) {
799 %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
806 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
808 std::vector
<IRInstructionData
*> InstrList
;
809 std::vector
<unsigned> UnsignedVec
;
811 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
812 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
813 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
814 Mapper
.initializeForBBs(*M
);
815 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
817 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
818 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
819 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
822 // In most cases, the illegal instructions we are collecting don't require any
823 // sort of setup. In these cases, we can just only have illegal instructions,
824 // and the mapper will create 0 length vectors, and we can check that.
826 // In cases where we have legal instructions needed to set up the illegal
827 // instruction, to check illegal instructions are assigned unsigned integers
828 // from the maximum value decreasing to 0, it will be greater than a legal
829 // instruction that comes after. So to check that we have an illegal
830 // instruction, we place a legal instruction after an illegal instruction, and
831 // check that the illegal unsigned integer is greater than the unsigned integer
832 // of the legal instruction.
834 // Checks that an alloca instruction is mapped to be illegal.
835 TEST(IRInstructionMapper
, AllocaIllegal
) {
836 StringRef ModuleString
= R
"(
837 define i32 @f(i32 %a, i32 %b) {
843 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
845 std::vector
<IRInstructionData
*> InstrList
;
846 std::vector
<unsigned> UnsignedVec
;
848 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
849 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
850 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
851 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
853 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
854 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
855 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
858 // Checks that an getelementptr instruction is mapped to be legal. And that
859 // the operands in getelementpointer instructions are the exact same after the
860 // first element operand, which only requires the same type.
861 TEST(IRInstructionMapper
, GetElementPtrSameEndOperands
) {
862 StringRef ModuleString
= R
"(
863 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
864 %struct.ST = type { i32, double, %struct.RT }
865 define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
867 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
868 %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 0
872 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
874 std::vector
<IRInstructionData
*> InstrList
;
875 std::vector
<unsigned> UnsignedVec
;
877 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
878 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
879 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
880 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
882 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
883 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
884 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
887 // Check that when the operands in getelementpointer instructions are not the
888 // exact same after the first element operand, the instructions are mapped to
890 TEST(IRInstructionMapper
, GetElementPtrDifferentEndOperands
) {
891 StringRef ModuleString
= R
"(
892 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
893 %struct.ST = type { i32, double, %struct.RT }
894 define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
896 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
897 %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 2
901 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
903 std::vector
<IRInstructionData
*> InstrList
;
904 std::vector
<unsigned> UnsignedVec
;
906 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
907 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
908 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
909 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
911 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
912 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
913 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
916 // Check that when the operands in getelementpointer instructions are not the
917 // same initial base type, each instruction is mapped to a different value.
918 TEST(IRInstructionMapper
, GetElementPtrDifferentBaseType
) {
919 StringRef ModuleString
= R
"(
920 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
921 %struct.ST = type { i32, double, %struct.RT }
922 define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
924 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a
925 %1 = getelementptr inbounds %struct.RT, %struct.RT* %r, i64 %b
929 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
931 std::vector
<IRInstructionData
*> InstrList
;
932 std::vector
<unsigned> UnsignedVec
;
934 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
935 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
936 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
937 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
939 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
940 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
941 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
944 // Check that when the operands in getelementpointer instructions do not have
945 // the same inbounds modifier, they are not counted as the same.
946 TEST(IRInstructionMapper
, GetElementPtrDifferentInBounds
) {
947 StringRef ModuleString
= R
"(
948 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
949 %struct.ST = type { i32, double, %struct.RT }
950 define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
952 %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
953 %1 = getelementptr %struct.ST, %struct.ST* %s, i64 %b, i32 0
957 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
959 std::vector
<IRInstructionData
*> InstrList
;
960 std::vector
<unsigned> UnsignedVec
;
962 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
963 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
964 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
965 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
967 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
968 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
969 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
972 // Checks that indirect call instructions are mapped to be illegal when it is
973 // specified to disallow them.
974 TEST(IRInstructionMapper
, CallsIllegalIndirect
) {
975 StringRef ModuleString
= R
"(
976 define i32 @f(void()* %func) {
982 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
984 std::vector
<IRInstructionData
*> InstrList
;
985 std::vector
<unsigned> UnsignedVec
;
987 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
988 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
989 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
990 Mapper
.InstClassifier
.EnableIndirectCalls
= false;
991 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
993 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
994 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
995 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
998 // Checks that indirect call instructions are mapped to be legal when it is not
999 // specified to disallow them.
1000 TEST(IRInstructionMapper
, CallsLegalIndirect
) {
1001 StringRef ModuleString
= R
"(
1002 define i32 @f(void()* %func) {
1008 LLVMContext Context
;
1009 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1011 std::vector
<IRInstructionData
*> InstrList
;
1012 std::vector
<unsigned> UnsignedVec
;
1014 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1015 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1016 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1017 Mapper
.InstClassifier
.EnableIndirectCalls
= true;
1018 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1020 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1021 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1024 // Checks that a call instruction is mapped to be legal. Here we check that
1025 // a call with the same name, and same types are mapped to the same
1027 TEST(IRInstructionMapper
, CallsSameTypeSameName
) {
1028 StringRef ModuleString
= R
"(
1029 declare i32 @f1(i32, i32)
1030 define i32 @f(i32 %a, i32 %b) {
1032 %0 = call i32 @f1(i32 %a, i32 %b)
1033 %1 = call i32 @f1(i32 %a, i32 %b)
1036 LLVMContext Context
;
1037 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1039 std::vector
<IRInstructionData
*> InstrList
;
1040 std::vector
<unsigned> UnsignedVec
;
1042 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1043 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1044 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1045 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1047 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1048 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1049 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1052 // Here we check that a calls with different names, but the same arguments types
1053 // are mapped to different value when specified that the name must match.
1054 TEST(IRInstructionMapper
, CallsSameArgTypeDifferentNameDisallowed
) {
1055 StringRef ModuleString
= R
"(
1056 declare i32 @f1(i32, i32)
1057 declare i32 @f2(i32, i32)
1058 define i32 @f(i32 %a, i32 %b) {
1060 %0 = call i32 @f1(i32 %a, i32 %b)
1061 %1 = call i32 @f2(i32 %a, i32 %b)
1064 LLVMContext Context
;
1065 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1067 std::vector
<IRInstructionData
*> InstrList
;
1068 std::vector
<unsigned> UnsignedVec
;
1070 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1071 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1072 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1073 Mapper
.EnableMatchCallsByName
= true;
1074 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1076 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1077 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1078 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1081 // Here we check that a calls with different names, but the same arguments types
1082 // are mapped to the same value when it is not specifed that they must match.
1083 TEST(IRInstructionMapper
, CallsSameArgTypeDifferentName
) {
1084 StringRef ModuleString
= R
"(
1085 declare i32 @f1(i32, i32)
1086 declare i32 @f2(i32, i32)
1087 define i32 @f(i32 %a, i32 %b) {
1089 %0 = call i32 @f1(i32 %a, i32 %b)
1090 %1 = call i32 @f2(i32 %a, i32 %b)
1093 LLVMContext Context
;
1094 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1096 std::vector
<IRInstructionData
*> InstrList
;
1097 std::vector
<unsigned> UnsignedVec
;
1099 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1100 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1101 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1102 Mapper
.EnableMatchCallsByName
= false;
1103 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1105 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1106 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1107 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1110 // Here we check that a calls with different names, and different arguments
1111 // types are mapped to different value.
1112 TEST(IRInstructionMapper
, CallsDifferentArgTypeDifferentName
) {
1113 StringRef ModuleString
= R
"(
1114 declare i32 @f1(i32, i32)
1115 declare i32 @f2(i32)
1116 define i32 @f(i32 %a, i32 %b) {
1118 %0 = call i32 @f1(i32 %a, i32 %b)
1119 %1 = call i32 @f2(i32 %a)
1122 LLVMContext Context
;
1123 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1125 std::vector
<IRInstructionData
*> InstrList
;
1126 std::vector
<unsigned> UnsignedVec
;
1128 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1129 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1130 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1131 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1133 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1134 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1135 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1138 // Here we check that calls with different names, and different return
1139 // types are mapped to different value.
1140 TEST(IRInstructionMapper
, CallsDifferentReturnTypeDifferentName
) {
1141 StringRef ModuleString
= R
"(
1142 declare i64 @f1(i32, i32)
1143 declare i32 @f2(i32, i32)
1144 define i32 @f(i32 %a, i32 %b) {
1146 %0 = call i64 @f1(i32 %a, i32 %b)
1147 %1 = call i32 @f2(i32 %a, i32 %b)
1150 LLVMContext Context
;
1151 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1153 std::vector
<IRInstructionData
*> InstrList
;
1154 std::vector
<unsigned> UnsignedVec
;
1156 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1157 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1158 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1159 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1161 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1162 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1163 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1166 // Here we check that calls with the same name, types, and parameters map to the
1167 // same unsigned integer.
1168 TEST(IRInstructionMapper
, CallsSameParameters
) {
1169 StringRef ModuleString
= R
"(
1170 declare i32 @f1(i32, i32)
1171 define i32 @f(i32 %a, i32 %b) {
1173 %0 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1174 %1 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1177 LLVMContext Context
;
1178 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1180 std::vector
<IRInstructionData
*> InstrList
;
1181 std::vector
<unsigned> UnsignedVec
;
1183 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1184 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1185 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1186 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1188 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1189 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1190 ASSERT_EQ(UnsignedVec
[0], UnsignedVec
[1]);
1193 // Here we check that calls with different tail call settings are mapped to
1194 // different values.
1195 TEST(IRInstructionMapper
, CallsDifferentTails
) {
1196 StringRef ModuleString
= R
"(
1197 declare i32 @f1(i32, i32)
1198 define i32 @f(i32 %a, i32 %b) {
1200 %0 = tail call i32 @f1(i32 %a, i32 %b)
1201 %1 = call i32 @f1(i32 %a, i32 %b)
1204 LLVMContext Context
;
1205 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1207 std::vector
<IRInstructionData
*> InstrList
;
1208 std::vector
<unsigned> UnsignedVec
;
1210 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1211 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1212 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1213 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1215 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1216 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1217 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1220 // Here we check that calls with different calling convention settings are
1221 // mapped to different values.
1222 TEST(IRInstructionMapper
, CallsDifferentCallingConventions
) {
1223 StringRef ModuleString
= R
"(
1224 declare i32 @f1(i32, i32)
1225 define i32 @f(i32 %a, i32 %b) {
1227 %0 = call fastcc i32 @f1(i32 %a, i32 %b)
1228 %1 = call i32 @f1(i32 %a, i32 %b)
1231 LLVMContext Context
;
1232 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1234 std::vector
<IRInstructionData
*> InstrList
;
1235 std::vector
<unsigned> UnsignedVec
;
1237 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1238 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1239 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1240 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1242 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1243 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1244 ASSERT_NE(UnsignedVec
[0], UnsignedVec
[1]);
1247 // Checks that an invoke instruction is mapped to be illegal. Invoke
1248 // instructions are considered to be illegal because of the change in the
1249 // control flow that is currently not recognized.
1250 TEST(IRInstructionMapper
, InvokeIllegal
) {
1251 StringRef ModuleString
= R
"(
1252 define i32 @f(i8 *%gep1, i32 %b) {
1254 invoke i32 undef(i8* undef)
1255 to label %invoke unwind label %lpad
1261 landingpad { i8*, i32 }
1265 LLVMContext Context
;
1266 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1268 std::vector
<IRInstructionData
*> InstrList
;
1269 std::vector
<unsigned> UnsignedVec
;
1271 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1272 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1273 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1274 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1276 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1277 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1278 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1281 // Checks that an callbr instructions are considered to be illegal. Callbr
1282 // instructions are considered to be illegal because of the change in the
1283 // control flow that is currently not recognized.
1284 TEST(IRInstructionMapper
, CallBrInstIllegal
) {
1285 StringRef ModuleString
= R
"(
1286 define void @test() {
1291 define i32 @f(i32 %a, i32 %b) {
1293 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]
1299 LLVMContext Context
;
1300 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1302 std::vector
<IRInstructionData
*> InstrList
;
1303 std::vector
<unsigned> UnsignedVec
;
1305 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1306 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1307 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1308 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1310 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1311 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1312 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1315 // Checks that an debuginfo records are mapped to be invisible. Since they
1316 // do not semantically change the program, they can be recognized as similar.
1317 TEST(IRInstructionMapper
, DebugInfoInvisible
) {
1318 StringRef ModuleString
= R
"(
1319 define i32 @f(i32 %a, i32 %b) {
1322 #dbg_value(i32 0, !0, !0, !0)
1327 !0 = distinct !{!"test\
00", i32 10})";
1328 LLVMContext Context
;
1329 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1331 std::vector
<IRInstructionData
*> InstrList
;
1332 std::vector
<unsigned> UnsignedVec
;
1334 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1335 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1336 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1337 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1339 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1340 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(3));
1343 // The following are all exception handling intrinsics. We do not currently
1344 // handle these instruction because they are very context dependent.
1346 // Checks that an eh.typeid.for intrinsic is mapped to be illegal.
1347 TEST(IRInstructionMapper
, ExceptionHandlingTypeIdIllegal
) {
1348 StringRef ModuleString
= R
"(
1349 @_ZTIi = external constant i8*
1352 %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
1356 declare i32 @llvm.eh.typeid.for(i8*))";
1357 LLVMContext Context
;
1358 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1360 std::vector
<IRInstructionData
*> InstrList
;
1361 std::vector
<unsigned> UnsignedVec
;
1363 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1364 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1365 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1366 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1368 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1369 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1370 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1373 // Checks that an eh.exceptioncode intrinsic is mapped to be illegal.
1374 TEST(IRInstructionMapper
, ExceptionHandlingExceptionCodeIllegal
) {
1375 StringRef ModuleString
= R
"(
1376 define i32 @f(i32 %a, i32 %b) {
1378 %0 = catchswitch within none [label %__except] unwind to caller
1381 %1 = catchpad within %0 [i8* null]
1382 catchret from %1 to label %__except
1385 %2 = call i32 @llvm.eh.exceptioncode(token %1)
1389 declare i32 @llvm.eh.exceptioncode(token))";
1390 LLVMContext Context
;
1391 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1393 std::vector
<IRInstructionData
*> InstrList
;
1394 std::vector
<unsigned> UnsignedVec
;
1396 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1397 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1398 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1399 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1401 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1402 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1403 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1406 // Checks that an eh.unwind intrinsic is mapped to be illegal.
1407 TEST(IRInstructionMapper
, ExceptionHandlingUnwindIllegal
) {
1408 StringRef ModuleString
= R
"(
1409 define i32 @f(i32 %a, i32 %b) {
1411 call void @llvm.eh.unwind.init()
1415 declare void @llvm.eh.unwind.init())";
1416 LLVMContext Context
;
1417 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1419 std::vector
<IRInstructionData
*> InstrList
;
1420 std::vector
<unsigned> UnsignedVec
;
1422 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1423 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1424 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1425 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1427 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1428 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1429 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1432 // Checks that an eh.exceptionpointer intrinsic is mapped to be illegal.
1433 TEST(IRInstructionMapper
, ExceptionHandlingExceptionPointerIllegal
) {
1434 StringRef ModuleString
= R
"(
1435 define i32 @f(i32 %a, i32 %b) {
1437 %0 = call i8* @llvm.eh.exceptionpointer.p0i8(i32 0)
1441 declare i8* @llvm.eh.exceptionpointer.p0i8(i32))";
1442 LLVMContext Context
;
1443 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1445 std::vector
<IRInstructionData
*> InstrList
;
1446 std::vector
<unsigned> UnsignedVec
;
1448 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1449 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1450 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1451 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1453 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1454 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1455 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1458 // Checks that a catchpad instruction is mapped to an illegal value.
1459 TEST(IRInstructionMapper
, CatchpadIllegal
) {
1460 StringRef ModuleString
= R
"(
1461 declare void @llvm.donothing() nounwind readnone
1463 define void @function() personality i8 3 {
1465 invoke void @llvm.donothing() to label %normal unwind label %exception
1467 %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1469 catchpad within %cs1 []
1474 LLVMContext Context
;
1475 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1477 std::vector
<IRInstructionData
*> InstrList
;
1478 std::vector
<unsigned> UnsignedVec
;
1480 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1481 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1482 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1483 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1485 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1486 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1487 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1490 // Checks that a cleanuppad instruction is mapped to an illegal value.
1491 TEST(IRInstructionMapper
, CleanuppadIllegal
) {
1492 StringRef ModuleString
= R
"(
1493 declare void @llvm.donothing() nounwind readnone
1495 define void @function() personality i8 3 {
1497 invoke void @llvm.donothing() to label %normal unwind label %exception
1499 %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1501 %clean = cleanuppad within none []
1506 LLVMContext Context
;
1507 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1509 std::vector
<IRInstructionData
*> InstrList
;
1510 std::vector
<unsigned> UnsignedVec
;
1512 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1513 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1514 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1515 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1517 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1518 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(1));
1519 ASSERT_GT(UnsignedVec
[0], Mapper
.IllegalInstrNumber
);
1522 // The following three instructions are memory transfer and setting based, which
1523 // are considered illegal since is extra checking needed to handle the address
1526 // Checks that a memset instruction is mapped to an illegal value when
1528 TEST(IRInstructionMapper
, MemSetIllegal
) {
1529 StringRef ModuleString
= R
"(
1530 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1532 define i64 @function(i64 %x, i64 %z, i64 %n) {
1534 %pool = alloca [59 x i64], align 4
1535 %tmp = bitcast [59 x i64]* %pool to i8*
1536 call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1537 %cmp3 = icmp eq i64 %n, 0
1542 LLVMContext Context
;
1543 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1545 std::vector
<IRInstructionData
*> InstrList
;
1546 std::vector
<unsigned> UnsignedVec
;
1548 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1549 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1550 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1551 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1552 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1554 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1555 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1556 ASSERT_TRUE(UnsignedVec
[2] < UnsignedVec
[0]);
1559 // Checks that a memcpy instruction is mapped to an illegal value when
1561 TEST(IRInstructionMapper
, MemCpyIllegal
) {
1562 StringRef ModuleString
= R
"(
1563 declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1565 define i64 @function(i64 %x, i64 %z, i64 %n) {
1567 %pool = alloca [59 x i64], align 4
1568 %tmp = bitcast [59 x i64]* %pool to i8*
1569 call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1570 %cmp3 = icmp eq i64 %n, 0
1575 LLVMContext Context
;
1576 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1578 std::vector
<IRInstructionData
*> InstrList
;
1579 std::vector
<unsigned> UnsignedVec
;
1581 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1582 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1583 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1584 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1585 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1587 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1588 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1589 ASSERT_GT(UnsignedVec
[2], UnsignedVec
[3]);
1590 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[0]);
1593 // Checks that a memmove instruction is mapped to an illegal value when
1595 TEST(IRInstructionMapper
, MemMoveIllegal
) {
1596 StringRef ModuleString
= R
"(
1597 declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1599 define i64 @function(i64 %x, i64 %z, i64 %n) {
1601 %pool = alloca [59 x i64], align 4
1602 %tmp = bitcast [59 x i64]* %pool to i8*
1603 call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1604 %cmp3 = icmp eq i64 %n, 0
1609 LLVMContext Context
;
1610 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1612 std::vector
<IRInstructionData
*> InstrList
;
1613 std::vector
<unsigned> UnsignedVec
;
1615 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1616 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1617 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1618 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1619 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1621 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1622 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(7));
1623 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[0]);
1626 // Checks that mem* instructions are mapped to an legal value when not
1627 // specified, and that all the intrinsics are marked differently.
1628 TEST(IRInstructionMapper
, MemOpsLegal
) {
1629 StringRef ModuleString
= R
"(
1630 declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1631 declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1632 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1634 define i64 @function(i64 %x, i64 %z, i64 %n) {
1636 %pool = alloca [59 x i64], align 4
1637 %tmp = bitcast [59 x i64]* %pool to i8*
1638 call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1639 call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1640 call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1641 %cmp3 = icmp eq i64 %n, 0
1646 LLVMContext Context
;
1647 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1649 std::vector
<IRInstructionData
*> InstrList
;
1650 std::vector
<unsigned> UnsignedVec
;
1652 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1653 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1654 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1655 Mapper
.InstClassifier
.EnableIntrinsics
= true;
1656 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1658 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1659 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(9));
1660 ASSERT_LT(UnsignedVec
[2], UnsignedVec
[3]);
1661 ASSERT_LT(UnsignedVec
[3], UnsignedVec
[4]);
1662 ASSERT_LT(UnsignedVec
[4], UnsignedVec
[5]);
1665 // Checks that a variable argument instructions are mapped to an illegal value.
1666 // We exclude variable argument instructions since variable arguments
1667 // requires extra checking of the argument list.
1668 TEST(IRInstructionMapper
, VarArgsIllegal
) {
1669 StringRef ModuleString
= R
"(
1670 declare void @llvm.va_start(i8*)
1671 declare void @llvm.va_copy(i8*, i8*)
1672 declare void @llvm.va_end(i8*)
1674 define i32 @func1(i32 %a, double %b, i8* %v, ...) nounwind {
1676 %a.addr = alloca i32, align 4
1677 %b.addr = alloca double, align 8
1678 %ap = alloca i8*, align 4
1679 %c = alloca i32, align 4
1680 store i32 %a, i32* %a.addr, align 4
1681 store double %b, double* %b.addr, align 8
1682 %ap1 = bitcast i8** %ap to i8*
1683 call void @llvm.va_start(i8* %ap1)
1684 store double %b, double* %b.addr, align 8
1685 store double %b, double* %b.addr, align 8
1686 %0 = va_arg i8** %ap, i32
1687 store double %b, double* %b.addr, align 8
1688 store double %b, double* %b.addr, align 8
1689 call void @llvm.va_copy(i8* %v, i8* %ap1)
1690 store double %b, double* %b.addr, align 8
1691 store double %b, double* %b.addr, align 8
1692 call void @llvm.va_end(i8* %ap1)
1693 store i32 %0, i32* %c, align 4
1694 %tmp = load i32, i32* %c, align 4
1697 LLVMContext Context
;
1698 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1700 std::vector
<IRInstructionData
*> InstrList
;
1701 std::vector
<unsigned> UnsignedVec
;
1703 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1704 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1705 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1706 Mapper
.InstClassifier
.EnableIntrinsics
= false;
1707 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1709 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
1710 ASSERT_EQ(UnsignedVec
.size(), static_cast<unsigned>(17));
1711 ASSERT_TRUE(UnsignedVec
[7] < UnsignedVec
[0]);
1712 ASSERT_TRUE(UnsignedVec
[13] < UnsignedVec
[10]);
1713 ASSERT_TRUE(UnsignedVec
[16] < UnsignedVec
[13]);
1716 // Check the length of adding two illegal instructions one after th other. We
1717 // should find that only one element is added for each illegal range.
1718 TEST(IRInstructionMapper
, RepeatedIllegalLength
) {
1719 StringRef ModuleString
= R
"(
1720 define i32 @f(i32 %a, i32 %b) {
1730 LLVMContext Context
;
1731 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1733 std::vector
<IRInstructionData
*> InstrList
;
1734 std::vector
<unsigned> UnsignedVec
;
1736 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1737 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1738 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1739 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1741 // Check that the size of the unsigned vector and the instruction list are the
1742 // same as a safety check.
1743 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1745 // Make sure that the unsigned vector is the expected size.
1746 ASSERT_TRUE(UnsignedVec
.size() == 6);
1749 // A helper function that accepts an instruction list from a module made up of
1750 // two blocks of two legal instructions and terminator, and checks them for
1751 // instruction similarity.
1752 static bool longSimCandCompare(std::vector
<IRInstructionData
*> &InstrList
,
1753 bool Structure
= false, unsigned Length
= 2,
1754 unsigned StartIdxOne
= 0,
1755 unsigned StartIdxTwo
= 3) {
1756 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1758 Start
= InstrList
.begin();
1759 End
= InstrList
.begin();
1761 std::advance(End
, StartIdxOne
+ Length
- 1);
1762 IRSimilarityCandidate
Cand1(StartIdxOne
, Length
, *Start
, *End
);
1764 Start
= InstrList
.begin();
1765 End
= InstrList
.begin();
1767 std::advance(Start
, StartIdxTwo
);
1768 std::advance(End
, StartIdxTwo
+ Length
- 1);
1769 IRSimilarityCandidate
Cand2(StartIdxTwo
, Length
, *Start
, *End
);
1771 return IRSimilarityCandidate::compareStructure(Cand1
, Cand2
);
1772 return IRSimilarityCandidate::isSimilar(Cand1
, Cand2
);
1775 // Checks that two adds with commuted operands are considered to be the same
1777 TEST(IRSimilarityCandidate
, CheckIdenticalInstructions
) {
1778 StringRef ModuleString
= R
"(
1779 define i32 @f(i32 %a, i32 %b) {
1785 LLVMContext Context
;
1786 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1788 std::vector
<IRInstructionData
*> InstrList
;
1789 std::vector
<unsigned> UnsignedVec
;
1791 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1792 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1793 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1794 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1796 // Check to make sure that we have a long enough region.
1797 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(3));
1798 // Check that the instructions were added correctly to both vectors.
1799 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1801 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1802 Start
= InstrList
.begin();
1803 End
= InstrList
.begin();
1804 std::advance(End
, 1);
1805 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
1806 IRSimilarityCandidate
Cand2(0, 2, *Start
, *End
);
1808 ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
1811 // Checks that comparison instructions are found to be similar instructions
1812 // when the operands are flipped and the predicate is also swapped.
1813 TEST(IRSimilarityCandidate
, PredicateIsomorphism
) {
1814 StringRef ModuleString
= R
"(
1815 define i32 @f(i32 %a, i32 %b) {
1817 %0 = icmp sgt i32 %a, %b
1821 %2 = icmp slt i32 %a, %b
1825 LLVMContext Context
;
1826 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1828 std::vector
<IRInstructionData
*> InstrList
;
1829 std::vector
<unsigned> UnsignedVec
;
1831 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1832 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1833 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1834 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1836 ASSERT_TRUE(InstrList
.size() > 5);
1837 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1839 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1840 Start
= InstrList
.begin();
1841 End
= InstrList
.begin();
1843 std::advance(End
, 1);
1844 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
1846 Start
= InstrList
.begin();
1847 End
= InstrList
.begin();
1849 std::advance(Start
, 3);
1850 std::advance(End
, 4);
1851 IRSimilarityCandidate
Cand2(3, 2, *Start
, *End
);
1853 ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
1856 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1857 // are able to differentiate between instructions that have different opcodes.
1858 TEST(IRSimilarityCandidate
, CheckRegionsDifferentInstruction
) {
1859 StringRef ModuleString
= R
"(
1860 define i32 @f(i32 %a, i32 %b) {
1870 LLVMContext Context
;
1871 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1873 std::vector
<IRInstructionData
*> InstrList
;
1874 std::vector
<unsigned> UnsignedVec
;
1876 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1877 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1878 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1879 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1881 // Check to make sure that we have a long enough region.
1882 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1883 // Check that the instructions were added correctly to both vectors.
1884 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1886 ASSERT_FALSE(longSimCandCompare(InstrList
));
1889 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1890 // are able to differentiate between instructions that have different types.
1891 TEST(IRSimilarityCandidate
, CheckRegionsDifferentTypes
) {
1892 StringRef ModuleString
= R
"(
1893 define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
1903 LLVMContext Context
;
1904 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1906 std::vector
<IRInstructionData
*> InstrList
;
1907 std::vector
<unsigned> UnsignedVec
;
1909 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1910 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1911 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1912 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1914 // Check to make sure that we have a long enough region.
1915 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1916 // Check that the instructions were added correctly to both vectors.
1917 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1919 ASSERT_FALSE(longSimCandCompare(InstrList
));
1922 // Check that debug records do not impact similarity. They are marked as
1924 TEST(IRSimilarityCandidate
, IdenticalWithDebug
) {
1925 StringRef ModuleString
= R
"(
1926 define i32 @f(i32 %a, i32 %b) {
1929 #dbg_value(i32 0, !0, !0, !0)
1934 #dbg_value(i32 1, !1, !1, !1)
1943 !0 = distinct !{!"test\
00", i32 10}
1944 !1 = distinct !{!"test\
00", i32 11})";
1945 LLVMContext Context
;
1946 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1948 std::vector
<IRInstructionData
*> InstrList
;
1949 std::vector
<unsigned> UnsignedVec
;
1951 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1952 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1953 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1954 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1956 // Check to make sure that we have a long enough region.
1957 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(9));
1958 // Check that the instructions were added correctly to both vectors.
1959 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1961 ASSERT_TRUE(longSimCandCompare(InstrList
));
1964 // Checks that IRSimilarityCandidates that include illegal instructions, are not
1965 // considered to be the same set of instructions. In these sets of instructions
1966 // the allocas are illegal.
1967 TEST(IRSimilarityCandidate
, IllegalInCandidate
) {
1968 StringRef ModuleString
= R
"(
1969 define i32 @f(i32 %a, i32 %b) {
1981 LLVMContext Context
;
1982 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
1984 std::vector
<IRInstructionData
*> InstrList
;
1985 std::vector
<unsigned> UnsignedVec
;
1987 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
1988 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
1989 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
1990 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
1992 // Check to make sure that we have a long enough region.
1993 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
1994 // Check that the instructions were added correctly to both vectors.
1995 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
1997 std::vector
<IRInstructionData
*>::iterator Start
, End
;
1999 Start
= InstrList
.begin();
2000 End
= InstrList
.begin();
2002 std::advance(End
, 2);
2003 IRSimilarityCandidate
Cand1(0, 3, *Start
, *End
);
2005 Start
= InstrList
.begin();
2006 End
= InstrList
.begin();
2008 std::advance(Start
, 3);
2009 std::advance(End
, 5);
2010 IRSimilarityCandidate
Cand2(3, 3, *Start
, *End
);
2011 ASSERT_FALSE(IRSimilarityCandidate::isSimilar(Cand1
, Cand2
));
2014 // Checks that different structure, in this case, where we introduce a new
2015 // needed input in one region, is recognized as different.
2016 TEST(IRSimilarityCandidate
, DifferentStructure
) {
2017 StringRef ModuleString
= R
"(
2018 define i32 @f(i32 %a, i32 %b) {
2028 LLVMContext Context
;
2029 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2031 std::vector
<IRInstructionData
*> InstrList
;
2032 std::vector
<unsigned> UnsignedVec
;
2034 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2035 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2036 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2037 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2039 // Check to make sure that we have a long enough region.
2040 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2041 // Check that the instructions were added correctly to both vectors.
2042 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2044 ASSERT_FALSE(longSimCandCompare(InstrList
, true));
2047 // Checks that comparison instructions are found to have the same structure
2048 // when the operands are flipped and the predicate is also swapped.
2049 TEST(IRSimilarityCandidate
, PredicateIsomorphismStructure
) {
2050 StringRef ModuleString
= R
"(
2051 define i32 @f(i32 %a, i32 %b) {
2053 %0 = icmp sgt i32 %a, %b
2057 %2 = icmp slt i32 %b, %a
2061 LLVMContext Context
;
2062 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2064 std::vector
<IRInstructionData
*> InstrList
;
2065 std::vector
<unsigned> UnsignedVec
;
2067 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2068 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2069 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2070 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2072 ASSERT_TRUE(InstrList
.size() > 5);
2073 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2075 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2078 // Checks that different predicates are counted as diferent.
2079 TEST(IRSimilarityCandidate
, PredicateDifference
) {
2080 StringRef ModuleString
= R
"(
2081 define i32 @f(i32 %a, i32 %b) {
2083 %0 = icmp sge i32 %a, %b
2087 %2 = icmp slt i32 %b, %a
2091 LLVMContext Context
;
2092 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2094 std::vector
<IRInstructionData
*> InstrList
;
2095 std::vector
<unsigned> UnsignedVec
;
2097 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2098 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2099 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2100 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2102 ASSERT_TRUE(InstrList
.size() > 5);
2103 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2105 ASSERT_FALSE(longSimCandCompare(InstrList
));
2108 // Checks that the same structure is recognized between two candidates. The
2109 // items %a and %b are used in the same way in both sets of instructions.
2110 TEST(IRSimilarityCandidate
, SameStructure
) {
2111 StringRef ModuleString
= R
"(
2112 define i32 @f(i32 %a, i32 %b) {
2122 LLVMContext Context
;
2123 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2125 std::vector
<IRInstructionData
*> InstrList
;
2126 std::vector
<unsigned> UnsignedVec
;
2128 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2129 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2130 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2131 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2133 // Check to make sure that we have a long enough region.
2134 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2135 // Check that the instructions were added correctly to both vectors.
2136 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2138 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2141 // Checks that the canonical numbering between two candidates matches the found
2142 // mapping between two candidates.
2143 TEST(IRSimilarityCandidate
, CanonicalNumbering
) {
2144 StringRef ModuleString
= R
"(
2145 define i32 @f(i32 %a, i32 %b) {
2155 LLVMContext Context
;
2156 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2158 std::vector
<IRInstructionData
*> InstrList
;
2159 std::vector
<unsigned> UnsignedVec
;
2161 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2162 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2163 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2164 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2166 // Check to make sure that we have a long enough region.
2167 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2168 // Check that the instructions were added correctly to both vectors.
2169 ASSERT_EQ(InstrList
.size(), UnsignedVec
.size());
2171 std::vector
<IRInstructionData
*>::iterator Start
, End
;
2173 Start
= InstrList
.begin();
2174 End
= InstrList
.begin();
2176 std::advance(End
, 1);
2177 IRSimilarityCandidate
Cand1(0, 2, *Start
, *End
);
2179 Start
= InstrList
.begin();
2180 End
= InstrList
.begin();
2182 std::advance(Start
, 3);
2183 std::advance(End
, 4);
2184 IRSimilarityCandidate
Cand2(3, 2, *Start
, *End
);
2185 DenseMap
<unsigned, DenseSet
<unsigned>> Mapping1
;
2186 DenseMap
<unsigned, DenseSet
<unsigned>> Mapping2
;
2187 ASSERT_TRUE(IRSimilarityCandidate::compareStructure(Cand1
, Cand2
, Mapping1
,
2189 IRSimilarityCandidate::createCanonicalMappingFor(Cand1
);
2190 Cand2
.createCanonicalRelationFrom(Cand1
, Mapping1
, Mapping2
);
2192 for (std::pair
<unsigned, DenseSet
<unsigned>> &P
: Mapping2
) {
2193 unsigned Source
= P
.first
;
2195 ASSERT_TRUE(Cand2
.getCanonicalNum(Source
).has_value());
2196 unsigned Canon
= *Cand2
.getCanonicalNum(Source
);
2197 ASSERT_TRUE(Cand1
.fromCanonicalNum(Canon
).has_value());
2198 unsigned Dest
= *Cand1
.fromCanonicalNum(Canon
);
2200 DenseSet
<unsigned>::iterator It
= P
.second
.find(Dest
);
2201 ASSERT_NE(It
, P
.second
.end());
2205 // Checks that the same structure is recognized between two candidates. While
2206 // the input names are reversed, they still perform the same overall operation.
2207 TEST(IRSimilarityCandidate
, DifferentNameSameStructure
) {
2208 StringRef ModuleString
= R
"(
2209 define i32 @f(i32 %a, i32 %b) {
2219 LLVMContext Context
;
2220 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2222 std::vector
<IRInstructionData
*> InstrList
;
2223 std::vector
<unsigned> UnsignedVec
;
2225 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2226 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2227 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2228 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2230 // Check to make sure that we have a long enough region.
2231 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(6));
2232 // Check that the instructions were added correctly to both vectors.
2233 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2235 ASSERT_TRUE(longSimCandCompare(InstrList
, true));
2238 // Checks that the same structure is recognized between two candidates when
2239 // the branches target other blocks inside the same region, the relative
2240 // distance between the blocks must be the same.
2241 TEST(IRSimilarityCandidate
, SameBranchStructureInternal
) {
2242 StringRef ModuleString
= R
"(
2243 define i32 @f(i32 %a, i32 %b) {
2254 define i32 @f2(i32 %a, i32 %b) {
2264 LLVMContext Context
;
2265 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2267 std::vector
<IRInstructionData
*> InstrList
;
2268 std::vector
<unsigned> UnsignedVec
;
2270 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2271 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2272 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2273 Mapper
.InstClassifier
.EnableBranches
= true;
2274 Mapper
.initializeForBBs(*M
);
2275 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2277 // Check to make sure that we have a long enough region.
2278 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2279 // Check that the instructions were added correctly to both vectors.
2280 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2282 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 5, 0, 6));
2285 // Checks that the different structure is recognized between two candidates,
2286 // when the branches target other blocks inside the same region, the relative
2287 // distance between the blocks must be the same.
2288 TEST(IRSimilarityCandidate
, DifferentBranchStructureInternal
) {
2289 StringRef ModuleString
= R
"(
2290 define i32 @f(i32 %a, i32 %b) {
2305 define i32 @f2(i32 %a, i32 %b) {
2319 LLVMContext Context
;
2320 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2322 std::vector
<IRInstructionData
*> InstrList
;
2323 std::vector
<unsigned> UnsignedVec
;
2325 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2326 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2327 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2328 Mapper
.InstClassifier
.EnableBranches
= true;
2329 Mapper
.initializeForBBs(*M
);
2330 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2332 // Check to make sure that we have a long enough region.
2333 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(18));
2334 // Check that the instructions were added correctly to both vectors.
2335 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2337 ASSERT_FALSE(longSimCandCompare(InstrList
, true, 6, 0, 9));
2340 // Checks that the same structure is recognized between two candidates, when
2341 // the branches target other blocks outside region, the relative distance
2342 // does not need to be the same.
2343 TEST(IRSimilarityCandidate
, SameBranchStructureOutside
) {
2344 StringRef ModuleString
= R
"(
2345 define i32 @f(i32 %a, i32 %b) {
2356 define i32 @f2(i32 %a, i32 %b) {
2366 LLVMContext Context
;
2367 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2369 std::vector
<IRInstructionData
*> InstrList
;
2370 std::vector
<unsigned> UnsignedVec
;
2372 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2373 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2374 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2375 Mapper
.InstClassifier
.EnableBranches
= true;
2376 Mapper
.initializeForBBs(*M
);
2377 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2379 // Check to make sure that we have a long enough region.
2380 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2381 // Check that the instructions were added correctly to both vectors.
2382 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2384 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 3, 0, 6));
2387 // Checks that the same structure is recognized between two candidates, when
2388 // the branches target other blocks outside region, the relative distance
2389 // does not need to be the same.
2390 TEST(IRSimilarityCandidate
, DifferentBranchStructureOutside
) {
2391 StringRef ModuleString
= R
"(
2392 define i32 @f(i32 %a, i32 %b) {
2403 define i32 @f2(i32 %a, i32 %b) {
2417 LLVMContext Context
;
2418 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2420 std::vector
<IRInstructionData
*> InstrList
;
2421 std::vector
<unsigned> UnsignedVec
;
2423 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2424 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2425 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2426 Mapper
.InstClassifier
.EnableBranches
= true;
2427 Mapper
.initializeForBBs(*M
);
2428 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2430 // Check to make sure that we have a long enough region.
2431 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(15));
2432 // Check that the instructions were added correctly to both vectors.
2433 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2435 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 3, 0, 6));
2438 // Checks that the same structure is recognized between two candidates,
2439 // when the phi predecessor are other blocks inside the same region,
2440 // the relative distance between the blocks must be the same.
2441 TEST(IRSimilarityCandidate
, SamePHIStructureInternal
) {
2442 StringRef ModuleString
= R
"(
2443 define i32 @f(i32 %a, i32 %b) {
2449 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2455 define i32 @f2(i32 %a, i32 %b) {
2461 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2466 LLVMContext Context
;
2467 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2469 std::vector
<IRInstructionData
*> InstrList
;
2470 std::vector
<unsigned> UnsignedVec
;
2472 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2473 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2474 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2475 Mapper
.InstClassifier
.EnableBranches
= true;
2476 Mapper
.initializeForBBs(*M
);
2477 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2479 // Check to make sure that we have a long enough region.
2480 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(12));
2481 // Check that the instructions were added correctly to both vectors.
2482 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2484 ASSERT_TRUE(longSimCandCompare(InstrList
, true, 4, 0, 6));
2487 // Checks that the different structure is recognized between two candidates,
2488 // when the phi predecessor are other blocks inside the same region,
2489 // the relative distance between the blocks must be the same.
2490 TEST(IRSimilarityCandidate
, DifferentPHIStructureInternal
) {
2491 StringRef ModuleString
= R
"(
2492 define i32 @f(i32 %a, i32 %b) {
2500 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2506 define i32 @f2(i32 %a, i32 %b) {
2514 %0 = phi i32 [ %a, %bb0 ], [ %b, %bb3 ]
2519 LLVMContext Context
;
2520 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2522 std::vector
<IRInstructionData
*> InstrList
;
2523 std::vector
<unsigned> UnsignedVec
;
2525 SpecificBumpPtrAllocator
<IRInstructionData
> InstDataAllocator
;
2526 SpecificBumpPtrAllocator
<IRInstructionDataList
> IDLAllocator
;
2527 IRInstructionMapper
Mapper(&InstDataAllocator
, &IDLAllocator
);
2528 Mapper
.InstClassifier
.EnableBranches
= true;
2529 Mapper
.initializeForBBs(*M
);
2530 getVectors(*M
, Mapper
, InstrList
, UnsignedVec
);
2532 // Check to make sure that we have a long enough region.
2533 ASSERT_EQ(InstrList
.size(), static_cast<unsigned>(14));
2534 // Check that the instructions were added correctly to both vectors.
2535 ASSERT_TRUE(InstrList
.size() == UnsignedVec
.size());
2537 ASSERT_FALSE(longSimCandCompare(InstrList
, true, 5, 0, 7));
2540 // Checks that two sets of identical instructions are found to be the same.
2541 // Both sequences of adds have the same operand ordering, and the same
2542 // instructions, making them strcturally equivalent.
2543 TEST(IRSimilarityIdentifier
, IdentitySimilarity
) {
2544 StringRef ModuleString
= R
"(
2545 define i32 @f(i32 %a, i32 %b) {
2555 LLVMContext Context
;
2556 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2558 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2559 getSimilarities(*M
, SimilarityCandidates
);
2561 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2562 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2563 ASSERT_TRUE(Cands
.size() == 2);
2564 unsigned InstIdx
= 0;
2565 for (IRSimilarityCandidate
&Cand
: Cands
) {
2566 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2572 // Checks that incorrect sequences are not found as similar. In this case,
2573 // we have different sequences of instructions.
2574 TEST(IRSimilarityIdentifier
, InstructionDifference
) {
2575 StringRef ModuleString
= R
"(
2576 define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2586 LLVMContext Context
;
2587 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2589 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2590 getSimilarities(*M
, SimilarityCandidates
);
2592 ASSERT_TRUE(SimilarityCandidates
.empty());
2595 // This test checks to see whether we can detect similarity for commutative
2596 // instructions where the operands have been reversed.
2597 TEST(IRSimilarityIdentifier
, CommutativeSimilarity
) {
2598 StringRef ModuleString
= R
"(
2599 define i32 @f(i32 %a, i32 %b) {
2609 LLVMContext Context
;
2610 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2612 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2613 getSimilarities(*M
, SimilarityCandidates
);
2615 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2616 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2617 ASSERT_TRUE(Cands
.size() == 2);
2618 unsigned InstIdx
= 0;
2619 for (IRSimilarityCandidate
&Cand
: Cands
) {
2620 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2626 // This test ensures that when the first instruction in a sequence is
2627 // a commutative instruction with the same value (mcomm_inst_same_val), but the
2628 // corresponding instruction (comm_inst_diff_val) is not, we mark the regions
2630 TEST(IRSimilarityIdentifier
, CommutativeSameValueFirstMisMatch
) {
2631 StringRef ModuleString
= R
"(
2632 define void @v_1_0(i64 %v_33) {
2634 %comm_inst_same_val = mul i64 undef, undef
2635 %add = add i64 %comm_inst_same_val, %v_33
2636 %comm_inst_diff_val = mul i64 0, undef
2637 %mul.i = add i64 %comm_inst_diff_val, %comm_inst_diff_val
2640 LLVMContext Context
;
2641 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2643 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2644 getSimilarities(*M
, SimilarityCandidates
);
2646 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2649 // This test makes sure that intrinsic functions that are marked commutative
2650 // are still treated as non-commutative since they are function calls.
2651 TEST(IRSimilarityIdentifier
, IntrinsicCommutative
) {
2652 // If treated as commutative, we will fail to find a valid mapping, causing
2653 // an assertion error.
2654 StringRef ModuleString
= R
"(
2655 define void @foo() {
2657 %0 = call i16 @llvm.smul.fix.i16(i16 16384, i16 16384, i32 15)
2658 store i16 %0, i16* undef, align 1
2659 %1 = icmp eq i16 undef, 8192
2661 %2 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 16384, i32 15)
2662 store i16 %2, i16* undef, align 1
2663 %3 = icmp eq i16 undef, -8192
2665 %4 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 -16384, i32 15)
2671 ; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
2672 declare i16 @llvm.smul.fix.i16(i16, i16, i32 immarg))";
2673 LLVMContext Context
;
2674 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2676 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2677 getSimilarities(*M
, SimilarityCandidates
);
2679 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2682 // This test checks to see whether we can detect different structure in
2683 // commutative instructions. In this case, the second operand in the second
2684 // add is different.
2685 TEST(IRSimilarityIdentifier
, NoCommutativeSimilarity
) {
2686 StringRef ModuleString
= R
"(
2687 define i32 @f(i32 %a, i32 %b) {
2697 LLVMContext Context
;
2698 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2700 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2701 getSimilarities(*M
, SimilarityCandidates
);
2703 ASSERT_TRUE(SimilarityCandidates
.size() == 0);
2706 // Check that we are not finding similarity in non commutative
2707 // instructions. That is, while the instruction and operands used are the same
2708 // in the two subtraction sequences, they are in a different order, and cannot
2709 // be counted as the same since a subtraction is not commutative.
2710 TEST(IRSimilarityIdentifier
, NonCommutativeDifference
) {
2711 StringRef ModuleString
= R
"(
2712 define i32 @f(i32 %a, i32 %b) {
2722 LLVMContext Context
;
2723 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2725 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2726 getSimilarities(*M
, SimilarityCandidates
);
2728 ASSERT_TRUE(SimilarityCandidates
.empty());
2731 // Check that we find similarity despite changing the register names.
2732 TEST(IRSimilarityIdentifier
, MappingSimilarity
) {
2733 StringRef ModuleString
= R
"(
2734 define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2744 LLVMContext Context
;
2745 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2747 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2748 getSimilarities(*M
, SimilarityCandidates
);
2750 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2751 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2752 ASSERT_TRUE(Cands
.size() == 2);
2753 unsigned InstIdx
= 0;
2754 for (IRSimilarityCandidate
&Cand
: Cands
) {
2755 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2761 // Check that we find instances of swapped predicate isomorphism. That is,
2762 // for predicates that can be flipped, e.g. greater than to less than,
2763 // we can identify that instances of these different literal predicates, but are
2764 // the same within a single swap can be found.
2765 TEST(IRSimilarityIdentifier
, PredicateIsomorphism
) {
2766 StringRef ModuleString
= R
"(
2767 define i32 @f(i32 %a, i32 %b) {
2770 %1 = icmp sgt i32 %b, %a
2774 %3 = icmp slt i32 %a, %b
2777 LLVMContext Context
;
2778 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2780 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2781 getSimilarities(*M
, SimilarityCandidates
);
2783 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2784 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2785 ASSERT_TRUE(Cands
.size() == 2);
2786 unsigned InstIdx
= 0;
2787 for (IRSimilarityCandidate
&Cand
: Cands
) {
2788 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2794 // Checks that constants are detected as the same operand in each use in the
2795 // sequences of instructions. Also checks that we can find structural
2796 // equivalence using constants. In this case the 1 has the same use pattern as
2798 TEST(IRSimilarityIdentifier
, ConstantMappingSimilarity
) {
2799 StringRef ModuleString
= R
"(
2800 define i32 @f(i32 %a, i32 %b) {
2803 %1 = icmp sgt i32 %b, 1
2807 %3 = icmp sgt i32 %b, %a
2810 LLVMContext Context
;
2811 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2813 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2814 getSimilarities(*M
, SimilarityCandidates
);
2816 ASSERT_TRUE(SimilarityCandidates
.size() == 1);
2817 for (std::vector
<IRSimilarityCandidate
> &Cands
: SimilarityCandidates
) {
2818 ASSERT_TRUE(Cands
.size() == 2);
2819 unsigned InstIdx
= 0;
2820 for (IRSimilarityCandidate
&Cand
: Cands
) {
2821 ASSERT_TRUE(Cand
.getStartIdx() == InstIdx
);
2827 // Check that constants are uniquely identified. i.e. two different constants
2828 // are not considered the same. This means that this should not find any
2829 // structural similarity.
2830 TEST(IRSimilarityIdentifier
, ConstantMappingDifference
) {
2831 StringRef ModuleString
= R
"(
2832 define i32 @f(i32 %a, i32 %b) {
2835 %1 = icmp sgt i32 %b, 2
2839 %3 = icmp slt i32 %a, %b
2842 LLVMContext Context
;
2843 std::unique_ptr
<Module
> M
= makeLLVMModule(Context
, ModuleString
);
2845 std::vector
<std::vector
<IRSimilarityCandidate
>> SimilarityCandidates
;
2846 getSimilarities(*M
, SimilarityCandidates
);
2848 ASSERT_TRUE(SimilarityCandidates
.empty());