1 //===- IRSimilarityIdentifierTest.cpp - IRSimilarityIdentifier unit tests -===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for components for finding similarity such as the instruction mapper,
10 // suffix tree usage, and structural analysis.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Analysis/IRSimilarityIdentifier.h"
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/Allocator.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "gtest/gtest.h"
21 
22 using namespace llvm;
23 using namespace IRSimilarity;
24 
25 static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
26                                               StringRef ModuleStr) {
27   SMDiagnostic Err;
28   std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
29   assert(M && "Bad LLVM IR?");
30   return M;
31 }
32 
33 void getVectors(Module &M, IRInstructionMapper &Mapper,
34                 std::vector<IRInstructionData *> &InstrList,
35                 std::vector<unsigned> &UnsignedVec) {
36   for (Function &F : M)
37     for (BasicBlock &BB : F)
38       Mapper.convertToUnsignedVec(BB, InstrList, UnsignedVec);
39 }
40 
41 void getSimilarities(
42     Module &M,
43     std::vector<std::vector<IRSimilarityCandidate>> &SimilarityCandidates) {
44   IRSimilarityIdentifier Identifier;
45   SimilarityCandidates = Identifier.findSimilarity(M);
46 }
47 
48 // Checks that different opcodes are mapped to different values
49 TEST(IRInstructionMapper, OpcodeDifferentiation) {
50   StringRef ModuleString = R"(
51                           define i32 @f(i32 %a, i32 %b) {
52                           bb0:
53                              %0 = add i32 %a, %b
54                              %1 = mul i32 %a, %b
55                              ret i32 0
56                           })";
57   LLVMContext Context;
58   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
59 
60   std::vector<IRInstructionData *> InstrList;
61   std::vector<unsigned> UnsignedVec;
62 
63   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
64   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
65   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
66   getVectors(*M, Mapper, InstrList, UnsignedVec);
67 
68   // Check that the size of the unsigned vector and the instruction list are the
69   // same as a safety check.
70   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
71 
72   // Make sure that the unsigned vector is the expected size.
73   ASSERT_TRUE(UnsignedVec.size() == 3);
74 
75   // Check whether the instructions are not mapped to the same value.
76   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
77 }
78 
79 // Checks that the same opcodes and types are mapped to the same values.
80 TEST(IRInstructionMapper, OpcodeTypeSimilarity) {
81   StringRef ModuleString = R"(
82                           define i32 @f(i32 %a, i32 %b) {
83                           bb0:
84                              %0 = add i32 %a, %b
85                              %1 = add i32 %b, %a
86                              ret i32 0
87                           })";
88   LLVMContext Context;
89   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
90 
91   std::vector<IRInstructionData *> InstrList;
92   std::vector<unsigned> UnsignedVec;
93 
94   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
95   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
96   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
97   getVectors(*M, Mapper, InstrList, UnsignedVec);
98 
99   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
100   ASSERT_TRUE(UnsignedVec.size() == 3);
101 
102   // Check whether the instructions are mapped to the same value.
103   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
104 }
105 
106 // Checks that the same opcode and different types are mapped to different
107 // values.
108 TEST(IRInstructionMapper, TypeDifferentiation) {
109   StringRef ModuleString = R"(
110                           define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
111                           bb0:
112                              %0 = add i32 %a, %b
113                              %1 = add i64 %c, %d
114                              ret i32 0
115                           })";
116   LLVMContext Context;
117   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
118 
119   std::vector<IRInstructionData *> InstrList;
120   std::vector<unsigned> UnsignedVec;
121 
122   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
123   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
124   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
125   getVectors(*M, Mapper, InstrList, UnsignedVec);
126 
127   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
128   ASSERT_TRUE(UnsignedVec.size() == 3);
129   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
130 }
131 
132 // Checks that different predicates map to different values.
133 TEST(IRInstructionMapper, PredicateDifferentiation) {
134   StringRef ModuleString = R"(
135                           define i32 @f(i32 %a, i32 %b) {
136                           bb0:
137                              %0 = icmp sge i32 %b, %a
138                              %1 = icmp slt i32 %a, %b
139                              ret i32 0
140                           })";
141   LLVMContext Context;
142   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
143 
144   std::vector<IRInstructionData *> InstrList;
145   std::vector<unsigned> UnsignedVec;
146 
147   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
148   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
149   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
150   getVectors(*M, Mapper, InstrList, UnsignedVec);
151 
152   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
153   ASSERT_TRUE(UnsignedVec.size() == 3);
154   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
155 }
156 
157 // Checks that predicates where that can be considered the same when the
158 // operands are swapped, i.e. greater than to less than are mapped to the same
159 // unsigned integer.
160 TEST(IRInstructionMapper, PredicateIsomorphism) {
161   StringRef ModuleString = R"(
162                           define i32 @f(i32 %a, i32 %b) {
163                           bb0:
164                              %0 = icmp sgt i32 %a, %b
165                              %1 = icmp slt i32 %b, %a
166                              ret i32 0
167                           })";
168   LLVMContext Context;
169   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
170 
171   std::vector<IRInstructionData *> InstrList;
172   std::vector<unsigned> UnsignedVec;
173 
174   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
175   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
176   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
177   getVectors(*M, Mapper, InstrList, UnsignedVec);
178 
179   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
180   ASSERT_TRUE(UnsignedVec.size() == 3);
181   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
182 }
183 
184 // Checks that the same predicate maps to the same value.
185 TEST(IRInstructionMapper, PredicateSimilarity) {
186   StringRef ModuleString = R"(
187                           define i32 @f(i32 %a, i32 %b) {
188                           bb0:
189                              %0 = icmp slt i32 %a, %b
190                              %1 = icmp slt i32 %b, %a
191                              ret i32 0
192                           })";
193   LLVMContext Context;
194   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
195 
196   std::vector<IRInstructionData *> InstrList;
197   std::vector<unsigned> UnsignedVec;
198 
199   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
200   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
201   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
202   getVectors(*M, Mapper, InstrList, UnsignedVec);
203 
204   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
205   ASSERT_TRUE(UnsignedVec.size() == 3);
206   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
207 }
208 
209 // Checks that the same predicate maps to the same value for floating point
210 // CmpInsts.
211 TEST(IRInstructionMapper, FPPredicateSimilarity) {
212   StringRef ModuleString = R"(
213                           define i32 @f(double %a, double %b) {
214                           bb0:
215                              %0 = fcmp olt double %a, %b
216                              %1 = fcmp olt double %b, %a
217                              ret i32 0
218                           })";
219   LLVMContext Context;
220   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
221 
222   std::vector<IRInstructionData *> InstrList;
223   std::vector<unsigned> UnsignedVec;
224 
225   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
226   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
227   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
228   getVectors(*M, Mapper, InstrList, UnsignedVec);
229 
230   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
231   ASSERT_TRUE(UnsignedVec.size() == 3);
232   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
233 }
234 
235 // Checks that the different predicate maps to a different value for floating
236 // point CmpInsts.
237 TEST(IRInstructionMapper, FPPredicatDifference) {
238   StringRef ModuleString = R"(
239                           define i32 @f(double %a, double %b) {
240                           bb0:
241                              %0 = fcmp olt double %a, %b
242                              %1 = fcmp oge double %b, %a
243                              ret i32 0
244                           })";
245   LLVMContext Context;
246   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
247 
248   std::vector<IRInstructionData *> InstrList;
249   std::vector<unsigned> UnsignedVec;
250 
251   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
252   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
253   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
254   getVectors(*M, Mapper, InstrList, UnsignedVec);
255 
256   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
257   ASSERT_TRUE(UnsignedVec.size() == 3);
258   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
259 }
260 
261 // Checks that the zexts that have the same type parameters map to the same
262 // unsigned integer.
263 TEST(IRInstructionMapper, ZextTypeSimilarity) {
264   StringRef ModuleString = R"(
265                           define i32 @f(i32 %a) {
266                           bb0:
267                              %0 = zext i32  %a to i64
268                              %1 = zext i32  %a to i64
269                              ret i32 0
270                           })";
271   LLVMContext Context;
272   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
273 
274   std::vector<IRInstructionData *> InstrList;
275   std::vector<unsigned> UnsignedVec;
276 
277   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
278   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
279   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
280   getVectors(*M, Mapper, InstrList, UnsignedVec);
281 
282   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
283   ASSERT_TRUE(UnsignedVec.size() == 3);
284   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
285 }
286 
287 // Checks that the sexts that have the same type parameters map to the same
288 // unsigned integer.
289 TEST(IRInstructionMapper, SextTypeSimilarity) {
290   StringRef ModuleString = R"(
291                           define i32 @f(i32 %a) {
292                           bb0:
293                              %0 = sext i32  %a to i64
294                              %1 = sext i32  %a to i64
295                              ret i32 0
296                           })";
297   LLVMContext Context;
298   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
299 
300   std::vector<IRInstructionData *> InstrList;
301   std::vector<unsigned> UnsignedVec;
302 
303   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
304   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
305   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
306   getVectors(*M, Mapper, InstrList, UnsignedVec);
307 
308   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
309   ASSERT_TRUE(UnsignedVec.size() == 3);
310   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
311 }
312 
313 // Checks that the zexts that have the different type parameters map to the
314 // different unsigned integers.
315 TEST(IRInstructionMapper, ZextTypeDifference) {
316   StringRef ModuleString = R"(
317                           define i32 @f(i32 %a, i8 %b) {
318                           bb0:
319                              %0 = zext i32 %a to i64
320                              %1 = zext i8 %b to i32
321                              ret i32 0
322                           })";
323   LLVMContext Context;
324   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
325 
326   std::vector<IRInstructionData *> InstrList;
327   std::vector<unsigned> UnsignedVec;
328 
329   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
330   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
331   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
332   getVectors(*M, Mapper, InstrList, UnsignedVec);
333 
334   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
335   ASSERT_TRUE(UnsignedVec.size() == 3);
336   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
337 }
338 
339 // Checks that the sexts that have the different type parameters map to the
340 // different unsigned integers.
341 TEST(IRInstructionMapper, SextTypeDifference) {
342   StringRef ModuleString = R"(
343                           define i32 @f(i32 %a, i8 %b) {
344                           bb0:
345                              %0 = sext i32 %a to i64
346                              %1 = sext i8 %b to i32
347                              ret i32 0
348                           })";
349   LLVMContext Context;
350   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
351 
352   std::vector<IRInstructionData *> InstrList;
353   std::vector<unsigned> UnsignedVec;
354 
355   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
356   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
357   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
358   getVectors(*M, Mapper, InstrList, UnsignedVec);
359 
360   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
361   ASSERT_TRUE(UnsignedVec.size() == 3);
362   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
363 }
364 
365 // Checks that loads that have the same type are mapped to the same unsigned
366 // integer.
367 TEST(IRInstructionMapper, LoadSimilarType) {
368   StringRef ModuleString = R"(
369                           define i32 @f(i32* %a, i32* %b) {
370                           bb0:
371                              %0 = load i32, i32* %a
372                              %1 = load i32, i32* %b
373                              ret i32 0
374                           })";
375   LLVMContext Context;
376   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
377 
378   std::vector<IRInstructionData *> InstrList;
379   std::vector<unsigned> UnsignedVec;
380 
381   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
382   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
383   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
384   getVectors(*M, Mapper, InstrList, UnsignedVec);
385 
386   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
387   ASSERT_TRUE(UnsignedVec.size() == 3);
388   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
389 }
390 
391 // Checks that loads that have the different types are mapped to
392 // different unsigned integers.
393 TEST(IRInstructionMapper, LoadDifferentType) {
394   StringRef ModuleString = R"(
395                           define i32 @f(i32* %a, i64* %b) {
396                           bb0:
397                              %0 = load i32, i32* %a
398                              %1 = load i64, i64* %b
399                              ret i32 0
400                           })";
401   LLVMContext Context;
402   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
403 
404   std::vector<IRInstructionData *> InstrList;
405   std::vector<unsigned> UnsignedVec;
406 
407   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
408   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
409   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
410   getVectors(*M, Mapper, InstrList, UnsignedVec);
411 
412   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
413   ASSERT_TRUE(UnsignedVec.size() == 3);
414   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
415 }
416 
417 // Checks that loads that have the different aligns are mapped to different
418 // unsigned integers.
419 TEST(IRInstructionMapper, LoadDifferentAlign) {
420   StringRef ModuleString = R"(
421                           define i32 @f(i32* %a, i32* %b) {
422                           bb0:
423                              %0 = load i32, i32* %a, align 4
424                              %1 = load i32, i32* %b, align 8
425                              ret i32 0
426                           })";
427   LLVMContext Context;
428   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
429 
430   std::vector<IRInstructionData *> InstrList;
431   std::vector<unsigned> UnsignedVec;
432 
433   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
434   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
435   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
436   getVectors(*M, Mapper, InstrList, UnsignedVec);
437 
438   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
439   ASSERT_TRUE(UnsignedVec.size() == 3);
440   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
441 }
442 
443 // Checks that loads that have the different volatile settings are mapped to
444 // different unsigned integers.
445 TEST(IRInstructionMapper, LoadDifferentVolatile) {
446   StringRef ModuleString = R"(
447                           define i32 @f(i32* %a, i32* %b) {
448                           bb0:
449                              %0 = load volatile i32, i32* %a
450                              %1 = load i32, i32* %b
451                              ret i32 0
452                           })";
453   LLVMContext Context;
454   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
455 
456   std::vector<IRInstructionData *> InstrList;
457   std::vector<unsigned> UnsignedVec;
458 
459   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
460   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
461   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
462   getVectors(*M, Mapper, InstrList, UnsignedVec);
463 
464   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
465   ASSERT_TRUE(UnsignedVec.size() == 3);
466   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
467 }
468 
469 // Checks that loads that have the same volatile settings are mapped to
470 // different unsigned integers.
471 TEST(IRInstructionMapper, LoadSameVolatile) {
472   StringRef ModuleString = R"(
473                           define i32 @f(i32* %a, i32* %b) {
474                           bb0:
475                              %0 = load volatile i32, i32* %a
476                              %1 = load volatile i32, i32* %b
477                              ret i32 0
478                           })";
479   LLVMContext Context;
480   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
481 
482   std::vector<IRInstructionData *> InstrList;
483   std::vector<unsigned> UnsignedVec;
484 
485   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
486   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
487   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
488   getVectors(*M, Mapper, InstrList, UnsignedVec);
489 
490   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
491   ASSERT_TRUE(UnsignedVec.size() == 3);
492   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
493 }
494 
495 // Checks that loads that have the different atomicity settings are mapped to
496 // different unsigned integers.
497 TEST(IRInstructionMapper, LoadDifferentAtomic) {
498   StringRef ModuleString = R"(
499                           define i32 @f(i32* %a, i32* %b) {
500                           bb0:
501                              %0 = load atomic i32, i32* %a unordered, align 4
502                              %1 = load atomic i32, i32* %b monotonic, align 4
503                              ret i32 0
504                           })";
505   LLVMContext Context;
506   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
507 
508   std::vector<IRInstructionData *> InstrList;
509   std::vector<unsigned> UnsignedVec;
510 
511   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
512   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
513   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
514   getVectors(*M, Mapper, InstrList, UnsignedVec);
515 
516   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
517   ASSERT_TRUE(UnsignedVec.size() == 3);
518   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
519 }
520 
521 // Checks that loads that have the same atomicity settings are mapped to
522 // different unsigned integers.
523 TEST(IRInstructionMapper, LoadSameAtomic) {
524   StringRef ModuleString = R"(
525                           define i32 @f(i32* %a, i32* %b) {
526                           bb0:
527                              %0 = load atomic i32, i32* %a unordered, align 4
528                              %1 = load atomic i32, i32* %b unordered, align 4
529                              ret i32 0
530                           })";
531   LLVMContext Context;
532   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
533 
534   std::vector<IRInstructionData *> InstrList;
535   std::vector<unsigned> UnsignedVec;
536 
537   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
538   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
539   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
540   getVectors(*M, Mapper, InstrList, UnsignedVec);
541 
542   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
543   ASSERT_TRUE(UnsignedVec.size() == 3);
544   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
545 }
546 
547 // Checks that stores that have the same type are mapped to the same unsigned
548 // integer.
549 TEST(IRInstructionMapper, StoreSimilarType) {
550   StringRef ModuleString = R"(
551                           define i32 @f(i32* %a, i32* %b) {
552                           bb0:
553                              store i32 1, i32* %a
554                              store i32 2, i32* %a
555                              ret i32 0
556                           })";
557   LLVMContext Context;
558   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
559 
560   std::vector<IRInstructionData *> InstrList;
561   std::vector<unsigned> UnsignedVec;
562 
563   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
564   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
565   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
566   getVectors(*M, Mapper, InstrList, UnsignedVec);
567 
568   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
569   ASSERT_TRUE(UnsignedVec.size() == 3);
570   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
571 }
572 
573 // Checks that stores that have the different types are mapped to
574 // different unsigned integers.
575 TEST(IRInstructionMapper, StoreDifferentType) {
576   StringRef ModuleString = R"(
577                           define i32 @f(i32* %a, i64* %b) {
578                           bb0:
579                              store i32 1, i32* %a
580                              store i64 1, i64* %b
581                              ret i32 0
582                           })";
583   LLVMContext Context;
584   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
585 
586   std::vector<IRInstructionData *> InstrList;
587   std::vector<unsigned> UnsignedVec;
588 
589   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
590   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
591   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
592   getVectors(*M, Mapper, InstrList, UnsignedVec);
593 
594   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
595   ASSERT_TRUE(UnsignedVec.size() == 3);
596   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
597 }
598 
599 // Checks that stores that have the different aligns are mapped to different
600 // unsigned integers.
601 TEST(IRInstructionMapper, StoreDifferentAlign) {
602   StringRef ModuleString = R"(
603                           define i32 @f(i32* %a, i32* %b) {
604                           bb0:
605                              store i32 1, i32* %a, align 4
606                              store i32 1, i32* %b, align 8
607                              ret i32 0
608                           })";
609   LLVMContext Context;
610   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
611 
612   std::vector<IRInstructionData *> InstrList;
613   std::vector<unsigned> UnsignedVec;
614 
615   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
616   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
617   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
618   getVectors(*M, Mapper, InstrList, UnsignedVec);
619 
620   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
621   ASSERT_TRUE(UnsignedVec.size() == 3);
622   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
623 }
624 
625 // Checks that stores that have the different volatile settings are mapped to
626 // different unsigned integers.
627 TEST(IRInstructionMapper, StoreDifferentVolatile) {
628   StringRef ModuleString = R"(
629                           define i32 @f(i32* %a, i32* %b) {
630                           bb0:
631                              store volatile i32 1, i32* %a
632                              store i32 1, i32* %b
633                              ret i32 0
634                           })";
635   LLVMContext Context;
636   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
637 
638   std::vector<IRInstructionData *> InstrList;
639   std::vector<unsigned> UnsignedVec;
640 
641   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
642   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
643   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
644   getVectors(*M, Mapper, InstrList, UnsignedVec);
645 
646   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
647   ASSERT_TRUE(UnsignedVec.size() == 3);
648   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
649 }
650 
651 // Checks that stores that have the same volatile settings are mapped to
652 // different unsigned integers.
653 TEST(IRInstructionMapper, StoreSameVolatile) {
654   StringRef ModuleString = R"(
655                           define i32 @f(i32* %a, i32* %b) {
656                           bb0:
657                              store volatile i32 1, i32* %a
658                              store volatile i32 1, i32* %b
659                              ret i32 0
660                           })";
661   LLVMContext Context;
662   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
663 
664   std::vector<IRInstructionData *> InstrList;
665   std::vector<unsigned> UnsignedVec;
666 
667   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
668   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
669   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
670   getVectors(*M, Mapper, InstrList, UnsignedVec);
671 
672   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
673   ASSERT_TRUE(UnsignedVec.size() == 3);
674   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
675 }
676 
677 // Checks that loads that have the same atomicity settings are mapped to
678 // different unsigned integers.
679 TEST(IRInstructionMapper, StoreSameAtomic) {
680   StringRef ModuleString = R"(
681                           define i32 @f(i32* %a, i32* %b) {
682                           bb0:
683                              store atomic i32 1, i32* %a unordered, align 4
684                              store atomic i32 1, i32* %b unordered, align 4
685                              ret i32 0
686                           })";
687   LLVMContext Context;
688   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
689 
690   std::vector<IRInstructionData *> InstrList;
691   std::vector<unsigned> UnsignedVec;
692 
693   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
694   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
695   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
696   getVectors(*M, Mapper, InstrList, UnsignedVec);
697 
698   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
699   ASSERT_TRUE(UnsignedVec.size() == 3);
700   ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
701 }
702 
703 // Checks that loads that have the different atomicity settings are mapped to
704 // different unsigned integers.
705 TEST(IRInstructionMapper, StoreDifferentAtomic) {
706   StringRef ModuleString = R"(
707                           define i32 @f(i32* %a, i32* %b) {
708                           bb0:
709                              store atomic i32 1, i32* %a unordered, align 4
710                              store atomic i32 1, i32* %b monotonic, align 4
711                              ret i32 0
712                           })";
713   LLVMContext Context;
714   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
715 
716   std::vector<IRInstructionData *> InstrList;
717   std::vector<unsigned> UnsignedVec;
718 
719   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
720   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
721   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
722   getVectors(*M, Mapper, InstrList, UnsignedVec);
723 
724   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
725   ASSERT_TRUE(UnsignedVec.size() == 3);
726   ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
727 }
728 
729 // In most cases, the illegal instructions we are collecting don't require any
730 // sort of setup.  In these cases, we can just only have illegal instructions,
731 // and the mapper will create 0 length vectors, and we can check that.
732 
733 // In cases where we have legal instructions needed to set up the illegal
734 // instruction, to check illegal instructions are assigned unsigned integers
735 // from the maximum value decreasing to 0, it will be greater than a legal
736 // instruction that comes after.  So to check that we have an illegal
737 // instruction, we place a legal instruction after an illegal instruction, and
738 // check that the illegal unsigned integer is greater than the unsigned integer
739 // of the legal instruction.
740 
741 // Checks that the branch is mapped to be illegal since there is extra checking
742 // needed to ensure that a branch in one region is branching to an isomorphic
743 // location in a different region.
744 TEST(IRInstructionMapper, BranchIllegal) {
745   StringRef ModuleString = R"(
746                           define i32 @f(i32 %a, i32 %b) {
747                           bb0:
748                              %0 = icmp slt i32 %a, %b
749                              br i1 %0, label %bb0, label %bb1
750                           bb1:
751                              ret i32 0
752                           })";
753   LLVMContext Context;
754   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
755 
756   std::vector<IRInstructionData *> InstrList;
757   std::vector<unsigned> UnsignedVec;
758 
759   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
760   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
761   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
762   getVectors(*M, Mapper, InstrList, UnsignedVec);
763 
764   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
765   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
766 }
767 
768 // Checks that a PHINode is mapped to be illegal since there is extra checking
769 // needed to ensure that a branch in one region is bin an isomorphic
770 // location in a different region.
771 TEST(IRInstructionMapper, PhiIllegal) {
772   StringRef ModuleString = R"(
773                           define i32 @f(i32 %a, i32 %b) {
774                           bb0:
775                              %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
776                              ret i32 0
777                           bb1:
778                              ret i32 1
779                           })";
780   LLVMContext Context;
781   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
782 
783   std::vector<IRInstructionData *> InstrList;
784   std::vector<unsigned> UnsignedVec;
785 
786   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
787   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
788   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
789   getVectors(*M, Mapper, InstrList, UnsignedVec);
790 
791   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
792   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
793 }
794 
795 // Checks that an alloca instruction is mapped to be illegal.
796 TEST(IRInstructionMapper, AllocaIllegal) {
797   StringRef ModuleString = R"(
798                           define i32 @f(i32 %a, i32 %b) {
799                           bb0:
800                              %0 = alloca i32
801                              ret i32 0
802                           })";
803   LLVMContext Context;
804   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
805 
806   std::vector<IRInstructionData *> InstrList;
807   std::vector<unsigned> UnsignedVec;
808 
809   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
810   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
811   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
812   getVectors(*M, Mapper, InstrList, UnsignedVec);
813 
814   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
815   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
816 }
817 
818 // Checks that an getelementptr instruction is mapped to be legal.  And that
819 // the operands in getelementpointer instructions are the exact same after the
820 // first element operand, which only requires the same type.
821 TEST(IRInstructionMapper, GetElementPtrSameEndOperands) {
822   StringRef ModuleString = R"(
823     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
824     %struct.ST = type { i32, double, %struct.RT }
825     define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
826     bb0:
827        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
828        %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 0
829        ret i32 0
830     })";
831   LLVMContext Context;
832   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
833 
834   std::vector<IRInstructionData *> InstrList;
835   std::vector<unsigned> UnsignedVec;
836 
837   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
838   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
839   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
840   getVectors(*M, Mapper, InstrList, UnsignedVec);
841 
842   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
843   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
844   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
845 }
846 
847 // Check that when the operands in getelementpointer instructions are not the
848 // exact same after the first element operand, the instructions are mapped to
849 // different values.
850 TEST(IRInstructionMapper, GetElementPtrDifferentEndOperands) {
851   StringRef ModuleString = R"(
852     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
853     %struct.ST = type { i32, double, %struct.RT }
854     define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
855     bb0:
856        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
857        %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 2
858        ret i32 0
859     })";
860   LLVMContext Context;
861   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
862 
863   std::vector<IRInstructionData *> InstrList;
864   std::vector<unsigned> UnsignedVec;
865 
866   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
867   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
868   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
869   getVectors(*M, Mapper, InstrList, UnsignedVec);
870 
871   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
872   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
873   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
874 }
875 
876 // Check that when the operands in getelementpointer instructions are not the
877 // same initial base type, each instruction is mapped to a different value.
878 TEST(IRInstructionMapper, GetElementPtrDifferentBaseType) {
879   StringRef ModuleString = R"(
880     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
881     %struct.ST = type { i32, double, %struct.RT }
882     define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
883     bb0:
884        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a
885        %1 = getelementptr inbounds %struct.RT, %struct.RT* %r, i64 %b
886        ret i32 0
887     })";
888   LLVMContext Context;
889   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
890 
891   std::vector<IRInstructionData *> InstrList;
892   std::vector<unsigned> UnsignedVec;
893 
894   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
895   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
896   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
897   getVectors(*M, Mapper, InstrList, UnsignedVec);
898 
899   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
900   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
901   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
902 }
903 
904 // Check that when the operands in getelementpointer instructions do not have
905 // the same inbounds modifier, they are not counted as the same.
906 TEST(IRInstructionMapper, GetElementPtrDifferentInBounds) {
907   StringRef ModuleString = R"(
908     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
909     %struct.ST = type { i32, double, %struct.RT }
910     define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
911     bb0:
912        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
913        %1 = getelementptr %struct.ST, %struct.ST* %s, i64 %b, i32 0
914        ret i32 0
915     })";
916   LLVMContext Context;
917   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
918 
919   std::vector<IRInstructionData *> InstrList;
920   std::vector<unsigned> UnsignedVec;
921 
922   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
923   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
924   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
925   getVectors(*M, Mapper, InstrList, UnsignedVec);
926 
927   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
928   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
929   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
930 }
931 
932 // Checks that indirect call instructions are mapped to be illegal since we
933 // cannot guarantee the same function in two different cases.
934 TEST(IRInstructionMapper, CallsIllegalIndirect) {
935   StringRef ModuleString = R"(
936                           define i32 @f(void()* %func) {
937                           bb0:
938                              call void %func()
939                              ret i32 0
940                           })";
941   LLVMContext Context;
942   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
943 
944   std::vector<IRInstructionData *> InstrList;
945   std::vector<unsigned> UnsignedVec;
946 
947   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
948   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
949   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
950   getVectors(*M, Mapper, InstrList, UnsignedVec);
951 
952   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
953   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
954 }
955 
956 // Checks that a call instruction is mapped to be legal.  Here we check that
957 // a call with the same name, and same types are mapped to the same
958 // value.
959 TEST(IRInstructionMapper, CallsSameTypeSameName) {
960   StringRef ModuleString = R"(
961                           declare i32 @f1(i32, i32)
962                           define i32 @f(i32 %a, i32 %b) {
963                           bb0:
964                              %0 = call i32 @f1(i32 %a, i32 %b)
965                              %1 = call i32 @f1(i32 %a, i32 %b)
966                              ret i32 0
967                           })";
968   LLVMContext Context;
969   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
970 
971   std::vector<IRInstructionData *> InstrList;
972   std::vector<unsigned> UnsignedVec;
973 
974   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
975   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
976   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
977   getVectors(*M, Mapper, InstrList, UnsignedVec);
978 
979   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
980   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
981   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
982 }
983 
984 // Here we check that a calls with different names, but the same arguments types
985 // are mapped to different value.
986 TEST(IRInstructionMapper, CallsSameArgTypeDifferentName) {
987   StringRef ModuleString = R"(
988                           declare i32 @f1(i32, i32)
989                           declare i32 @f2(i32, i32)
990                           define i32 @f(i32 %a, i32 %b) {
991                           bb0:
992                              %0 = call i32 @f1(i32 %a, i32 %b)
993                              %1 = call i32 @f2(i32 %a, i32 %b)
994                              ret i32 0
995                           })";
996   LLVMContext Context;
997   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
998 
999   std::vector<IRInstructionData *> InstrList;
1000   std::vector<unsigned> UnsignedVec;
1001 
1002   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1003   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1004   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1005   getVectors(*M, Mapper, InstrList, UnsignedVec);
1006 
1007   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1008   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1009   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1010 }
1011 
1012 // Here we check that a calls with different names, and different arguments
1013 // types are mapped to different value.
1014 TEST(IRInstructionMapper, CallsDifferentArgTypeDifferentName) {
1015   StringRef ModuleString = R"(
1016                           declare i32 @f1(i32, i32)
1017                           declare i32 @f2(i32)
1018                           define i32 @f(i32 %a, i32 %b) {
1019                           bb0:
1020                              %0 = call i32 @f1(i32 %a, i32 %b)
1021                              %1 = call i32 @f2(i32 %a)
1022                              ret i32 0
1023                           })";
1024   LLVMContext Context;
1025   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1026 
1027   std::vector<IRInstructionData *> InstrList;
1028   std::vector<unsigned> UnsignedVec;
1029 
1030   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1031   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1032   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1033   getVectors(*M, Mapper, InstrList, UnsignedVec);
1034 
1035   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1036   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1037   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1038 }
1039 
1040 // Here we check that calls with different names, and different return
1041 // types are mapped to different value.
1042 TEST(IRInstructionMapper, CallsDifferentReturnTypeDifferentName) {
1043   StringRef ModuleString = R"(
1044                           declare i64 @f1(i32, i32)
1045                           declare i32 @f2(i32, i32)
1046                           define i32 @f(i32 %a, i32 %b) {
1047                           bb0:
1048                              %0 = call i64 @f1(i32 %a, i32 %b)
1049                              %1 = call i32 @f2(i32 %a, i32 %b)
1050                              ret i32 0
1051                           })";
1052   LLVMContext Context;
1053   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1054 
1055   std::vector<IRInstructionData *> InstrList;
1056   std::vector<unsigned> UnsignedVec;
1057 
1058   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1059   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1060   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1061   getVectors(*M, Mapper, InstrList, UnsignedVec);
1062 
1063   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1064   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1065   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1066 }
1067 
1068 // Here we check that calls with the same name, types, and parameters map to the
1069 // same unsigned integer.
1070 TEST(IRInstructionMapper, CallsSameParameters) {
1071   StringRef ModuleString = R"(
1072                           declare i32 @f1(i32, i32)
1073                           define i32 @f(i32 %a, i32 %b) {
1074                           bb0:
1075                              %0 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1076                              %1 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1077                              ret i32 0
1078                           })";
1079   LLVMContext Context;
1080   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1081 
1082   std::vector<IRInstructionData *> InstrList;
1083   std::vector<unsigned> UnsignedVec;
1084 
1085   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1086   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1087   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1088   getVectors(*M, Mapper, InstrList, UnsignedVec);
1089 
1090   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1091   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1092   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
1093 }
1094 
1095 // Here we check that calls with different tail call settings are mapped to
1096 // different values.
1097 TEST(IRInstructionMapper, CallsDifferentTails) {
1098   StringRef ModuleString = R"(
1099                           declare i32 @f1(i32, i32)
1100                           define i32 @f(i32 %a, i32 %b) {
1101                           bb0:
1102                              %0 = tail call i32 @f1(i32 %a, i32 %b)
1103                              %1 = call i32 @f1(i32 %a, i32 %b)
1104                              ret i32 0
1105                           })";
1106   LLVMContext Context;
1107   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1108 
1109   std::vector<IRInstructionData *> InstrList;
1110   std::vector<unsigned> UnsignedVec;
1111 
1112   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1113   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1114   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1115   getVectors(*M, Mapper, InstrList, UnsignedVec);
1116 
1117   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1118   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1119   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1120 }
1121 
1122 // Here we check that calls with different calling convention settings are
1123 // mapped to different values.
1124 TEST(IRInstructionMapper, CallsDifferentCallingConventions) {
1125   StringRef ModuleString = R"(
1126                           declare i32 @f1(i32, i32)
1127                           define i32 @f(i32 %a, i32 %b) {
1128                           bb0:
1129                              %0 = call fastcc i32 @f1(i32 %a, i32 %b)
1130                              %1 = call i32 @f1(i32 %a, i32 %b)
1131                              ret i32 0
1132                           })";
1133   LLVMContext Context;
1134   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1135 
1136   std::vector<IRInstructionData *> InstrList;
1137   std::vector<unsigned> UnsignedVec;
1138 
1139   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1140   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1141   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1142   getVectors(*M, Mapper, InstrList, UnsignedVec);
1143 
1144   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1145   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1146   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1147 }
1148 
1149 // Checks that an invoke instruction is mapped to be illegal. Invoke
1150 // instructions are considered to be illegal because of the change in the
1151 // control flow that is currently not recognized.
1152 TEST(IRInstructionMapper, InvokeIllegal) {
1153   StringRef ModuleString = R"(
1154                           define i32 @f(i8 *%gep1, i32 %b) {
1155                           then:
1156                             invoke i32 undef(i8* undef)
1157                                to label %invoke unwind label %lpad
1158 
1159                           invoke:
1160                             unreachable
1161 
1162                           lpad:
1163                             landingpad { i8*, i32 }
1164                                catch i8* null
1165                             unreachable
1166                           })";
1167   LLVMContext Context;
1168   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1169 
1170   std::vector<IRInstructionData *> InstrList;
1171   std::vector<unsigned> UnsignedVec;
1172 
1173   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1174   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1175   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1176   getVectors(*M, Mapper, InstrList, UnsignedVec);
1177 
1178   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1179   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1180 }
1181 
1182 // Checks that an callbr instructions are considered to be illegal.  Callbr
1183 // instructions are considered to be illegal because of the change in the
1184 // control flow that is currently not recognized.
1185 TEST(IRInstructionMapper, CallBrInstIllegal) {
1186   StringRef ModuleString = R"(
1187   define void @test() {
1188     fail:
1189       ret void
1190   }
1191 
1192   define i32 @f(i32 %a, i32 %b) {
1193       bb0:
1194         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]
1195       fail:
1196         ret i32 0
1197       normal:
1198         ret i32 0
1199   })";
1200   LLVMContext Context;
1201   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1202 
1203   std::vector<IRInstructionData *> InstrList;
1204   std::vector<unsigned> UnsignedVec;
1205 
1206   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1207   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1208   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1209   getVectors(*M, Mapper, InstrList, UnsignedVec);
1210 
1211   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1212   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1213 }
1214 
1215 // Checks that an debuginfo intrinsics are mapped to be invisible.  Since they
1216 // do not semantically change the program, they can be recognized as similar.
1217 TEST(IRInstructionMapper, DebugInfoInvisible) {
1218   StringRef ModuleString = R"(
1219                           define i32 @f(i32 %a, i32 %b) {
1220                           then:
1221                             %0 = add i32 %a, %b
1222                             call void @llvm.dbg.value(metadata !0)
1223                             %1 = add i32 %a, %b
1224                             ret i32 0
1225                           }
1226 
1227                           declare void @llvm.dbg.value(metadata)
1228                           !0 = distinct !{!"test\00", i32 10})";
1229   LLVMContext Context;
1230   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1231 
1232   std::vector<IRInstructionData *> InstrList;
1233   std::vector<unsigned> UnsignedVec;
1234 
1235   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1236   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1237   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1238   getVectors(*M, Mapper, InstrList, UnsignedVec);
1239 
1240   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1241   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1242 }
1243 
1244 // The following are all exception handling intrinsics.  We do not currently
1245 // handle these instruction because they are very context dependent.
1246 
1247 // Checks that an eh.typeid.for intrinsic is mapped to be illegal.
1248 TEST(IRInstructionMapper, ExceptionHandlingTypeIdIllegal) {
1249   StringRef ModuleString = R"(
1250     @_ZTIi = external constant i8*
1251     define i32 @f() {
1252     then:
1253       %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
1254       ret i32 0
1255     }
1256 
1257     declare i32 @llvm.eh.typeid.for(i8*))";
1258   LLVMContext Context;
1259   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1260 
1261   std::vector<IRInstructionData *> InstrList;
1262   std::vector<unsigned> UnsignedVec;
1263 
1264   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1265   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1266   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1267   getVectors(*M, Mapper, InstrList, UnsignedVec);
1268 
1269   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1270   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1271 }
1272 
1273 // Checks that an eh.exceptioncode intrinsic is mapped to be illegal.
1274 TEST(IRInstructionMapper, ExceptionHandlingExceptionCodeIllegal) {
1275   StringRef ModuleString = R"(
1276     define i32 @f(i32 %a, i32 %b) {
1277     entry:
1278       %0 = catchswitch within none [label %__except] unwind to caller
1279 
1280     __except:
1281       %1 = catchpad within %0 [i8* null]
1282       catchret from %1 to label %__except
1283 
1284     then:
1285       %2 = call i32 @llvm.eh.exceptioncode(token %1)
1286       ret i32 0
1287     }
1288 
1289     declare i32 @llvm.eh.exceptioncode(token))";
1290   LLVMContext Context;
1291   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1292 
1293   std::vector<IRInstructionData *> InstrList;
1294   std::vector<unsigned> UnsignedVec;
1295 
1296   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1297   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1298   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1299   getVectors(*M, Mapper, InstrList, UnsignedVec);
1300 
1301   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1302   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1303 }
1304 
1305 // Checks that an eh.unwind intrinsic is mapped to be illegal.
1306 TEST(IRInstructionMapper, ExceptionHandlingUnwindIllegal) {
1307   StringRef ModuleString = R"(
1308                           define i32 @f(i32 %a, i32 %b) {
1309                           entry:
1310                             call void @llvm.eh.unwind.init()
1311                             ret i32 0
1312                           }
1313 
1314                           declare void @llvm.eh.unwind.init())";
1315   LLVMContext Context;
1316   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1317 
1318   std::vector<IRInstructionData *> InstrList;
1319   std::vector<unsigned> UnsignedVec;
1320 
1321   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1322   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1323   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1324   getVectors(*M, Mapper, InstrList, UnsignedVec);
1325 
1326   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1327   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1328 }
1329 
1330 // Checks that an eh.exceptionpointer intrinsic is mapped to be illegal.
1331 TEST(IRInstructionMapper, ExceptionHandlingExceptionPointerIllegal) {
1332   StringRef ModuleString = R"(
1333                           define i32 @f(i32 %a, i32 %b) {
1334                           entry:
1335                             %0 = call i8* @llvm.eh.exceptionpointer.p0i8(i32 0)
1336                             ret i32 0
1337                           }
1338 
1339                           declare i8* @llvm.eh.exceptionpointer.p0i8(i32))";
1340   LLVMContext Context;
1341   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1342 
1343   std::vector<IRInstructionData *> InstrList;
1344   std::vector<unsigned> UnsignedVec;
1345 
1346   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1347   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1348   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1349   getVectors(*M, Mapper, InstrList, UnsignedVec);
1350 
1351   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1352   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1353 }
1354 
1355 // Checks that a catchpad instruction is mapped to an illegal value.
1356 TEST(IRInstructionMapper, CatchpadIllegal) {
1357   StringRef ModuleString = R"(
1358     declare void @llvm.donothing() nounwind readnone
1359 
1360     define void @function() personality i8 3 {
1361       entry:
1362         invoke void @llvm.donothing() to label %normal unwind label %exception
1363       exception:
1364         %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1365       catchpad1:
1366         catchpad within %cs1 []
1367         br label %normal
1368       normal:
1369         ret void
1370   })";
1371   LLVMContext Context;
1372   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1373 
1374   std::vector<IRInstructionData *> InstrList;
1375   std::vector<unsigned> UnsignedVec;
1376 
1377   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1378   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1379   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1380   getVectors(*M, Mapper, InstrList, UnsignedVec);
1381 
1382   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1383   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1384 }
1385 
1386 // Checks that a cleanuppad instruction is mapped to an illegal value.
1387 TEST(IRInstructionMapper, CleanuppadIllegal) {
1388   StringRef ModuleString = R"(
1389     declare void @llvm.donothing() nounwind readnone
1390 
1391     define void @function() personality i8 3 {
1392       entry:
1393         invoke void @llvm.donothing() to label %normal unwind label %exception
1394       exception:
1395         %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1396       catchpad1:
1397         %clean = cleanuppad within none []
1398         br label %normal
1399       normal:
1400         ret void
1401   })";
1402   LLVMContext Context;
1403   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1404 
1405   std::vector<IRInstructionData *> InstrList;
1406   std::vector<unsigned> UnsignedVec;
1407 
1408   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1409   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1410   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1411   getVectors(*M, Mapper, InstrList, UnsignedVec);
1412 
1413   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1414   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1415 }
1416 
1417 // The following three instructions are memory transfer and setting based, which
1418 // are considered illegal since is extra checking needed to handle the address
1419 // space checking.
1420 
1421 // Checks that a memset instruction is mapped to an illegal value.
1422 TEST(IRInstructionMapper, MemSetIllegal) {
1423   StringRef ModuleString = R"(
1424   declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1425 
1426   define i64 @function(i64 %x, i64 %z, i64 %n) {
1427   entry:
1428     %pool = alloca [59 x i64], align 4
1429     %tmp = bitcast [59 x i64]* %pool to i8*
1430     call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1431     %cmp3 = icmp eq i64 %n, 0
1432     %a = add i64 %x, %z
1433     %c = add i64 %x, %z
1434     ret i64 0
1435   })";
1436   LLVMContext Context;
1437   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1438 
1439   std::vector<IRInstructionData *> InstrList;
1440   std::vector<unsigned> UnsignedVec;
1441 
1442   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1443   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1444   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1445   getVectors(*M, Mapper, InstrList, UnsignedVec);
1446 
1447   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1448   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(6));
1449   ASSERT_TRUE(UnsignedVec[2] < UnsignedVec[1]);
1450 }
1451 
1452 // Checks that a memcpy instruction is mapped to an illegal value.
1453 TEST(IRInstructionMapper, MemCpyIllegal) {
1454   StringRef ModuleString = R"(
1455   declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1456 
1457   define i64 @function(i64 %x, i64 %z, i64 %n) {
1458   entry:
1459     %pool = alloca [59 x i64], align 4
1460     %tmp = bitcast [59 x i64]* %pool to i8*
1461     call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1462     %cmp3 = icmp eq i64 %n, 0
1463     %a = add i64 %x, %z
1464     %c = add i64 %x, %z
1465     ret i64 0
1466   })";
1467   LLVMContext Context;
1468   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1469 
1470   std::vector<IRInstructionData *> InstrList;
1471   std::vector<unsigned> UnsignedVec;
1472 
1473   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1474   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1475   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1476   getVectors(*M, Mapper, InstrList, UnsignedVec);
1477 
1478   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1479   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(6));
1480   ASSERT_TRUE(UnsignedVec[2] < UnsignedVec[1]);
1481 }
1482 
1483 // Checks that a memmove instruction is mapped to an illegal value.
1484 TEST(IRInstructionMapper, MemMoveIllegal) {
1485   StringRef ModuleString = R"(
1486   declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1487 
1488   define i64 @function(i64 %x, i64 %z, i64 %n) {
1489   entry:
1490     %pool = alloca [59 x i64], align 4
1491     %tmp = bitcast [59 x i64]* %pool to i8*
1492     call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1493     %cmp3 = icmp eq i64 %n, 0
1494     %a = add i64 %x, %z
1495     %c = add i64 %x, %z
1496     ret i64 0
1497   })";
1498   LLVMContext Context;
1499   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1500 
1501   std::vector<IRInstructionData *> InstrList;
1502   std::vector<unsigned> UnsignedVec;
1503 
1504   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1505   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1506   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1507   getVectors(*M, Mapper, InstrList, UnsignedVec);
1508 
1509   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1510   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(6));
1511   ASSERT_TRUE(UnsignedVec[2] < UnsignedVec[1]);
1512 }
1513 
1514 // Checks that a variable argument instructions are mapped to an illegal value.
1515 // We exclude variable argument instructions since variable arguments
1516 // requires extra checking of the argument list.
1517 TEST(IRInstructionMapper, VarArgsIllegal) {
1518   StringRef ModuleString = R"(
1519   declare void @llvm.va_start(i8*)
1520   declare void @llvm.va_copy(i8*, i8*)
1521   declare void @llvm.va_end(i8*)
1522 
1523   define i32 @func1(i32 %a, double %b, i8* %v, ...) nounwind {
1524   entry:
1525     %a.addr = alloca i32, align 4
1526     %b.addr = alloca double, align 8
1527     %ap = alloca i8*, align 4
1528     %c = alloca i32, align 4
1529     store i32 %a, i32* %a.addr, align 4
1530     store double %b, double* %b.addr, align 8
1531     %ap1 = bitcast i8** %ap to i8*
1532     call void @llvm.va_start(i8* %ap1)
1533     store double %b, double* %b.addr, align 8
1534     store double %b, double* %b.addr, align 8
1535     %0 = va_arg i8** %ap, i32
1536     store double %b, double* %b.addr, align 8
1537     store double %b, double* %b.addr, align 8
1538     call void @llvm.va_copy(i8* %v, i8* %ap1)
1539     store double %b, double* %b.addr, align 8
1540     store double %b, double* %b.addr, align 8
1541     call void @llvm.va_end(i8* %ap1)
1542     store i32 %0, i32* %c, align 4
1543     %tmp = load i32, i32* %c, align 4
1544     ret i32 %tmp
1545   })";
1546   LLVMContext Context;
1547   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1548 
1549   std::vector<IRInstructionData *> InstrList;
1550   std::vector<unsigned> UnsignedVec;
1551 
1552   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1553   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1554   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1555   getVectors(*M, Mapper, InstrList, UnsignedVec);
1556 
1557   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1558   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(16));
1559   ASSERT_TRUE(UnsignedVec[4] < UnsignedVec[3]);
1560   ASSERT_TRUE(UnsignedVec[7] < UnsignedVec[6]);
1561   ASSERT_TRUE(UnsignedVec[10] < UnsignedVec[9]);
1562   ASSERT_TRUE(UnsignedVec[13] < UnsignedVec[12]);
1563 }
1564 
1565 // Check the length of adding two illegal instructions one after th other.  We
1566 // should find that only one element is added for each illegal range.
1567 TEST(IRInstructionMapper, RepeatedIllegalLength) {
1568   StringRef ModuleString = R"(
1569                           define i32 @f(i32 %a, i32 %b) {
1570                           bb0:
1571                              %0 = add i32 %a, %b
1572                              %1 = mul i32 %a, %b
1573                              %2 = alloca i32
1574                              %3 = alloca i32
1575                              %4 = add i32 %a, %b
1576                              %5 = mul i32 %a, %b
1577                              ret i32 0
1578                           })";
1579   LLVMContext Context;
1580   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1581 
1582   std::vector<IRInstructionData *> InstrList;
1583   std::vector<unsigned> UnsignedVec;
1584 
1585   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1586   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1587   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1588   getVectors(*M, Mapper, InstrList, UnsignedVec);
1589 
1590   // Check that the size of the unsigned vector and the instruction list are the
1591   // same as a safety check.
1592   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1593 
1594   // Make sure that the unsigned vector is the expected size.
1595   ASSERT_TRUE(UnsignedVec.size() == 6);
1596 }
1597 
1598 // A helper function that accepts an instruction list from a module made up of
1599 // two blocks of two legal instructions and terminator, and checks them for
1600 // instruction similarity.
1601 static bool longSimCandCompare(std::vector<IRInstructionData *> &InstrList,
1602                                bool Structure = false) {
1603   std::vector<IRInstructionData *>::iterator Start, End;
1604 
1605   Start = InstrList.begin();
1606   End = InstrList.begin();
1607 
1608   std::advance(End, 1);
1609   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
1610 
1611   Start = InstrList.begin();
1612   End = InstrList.begin();
1613 
1614   std::advance(Start, 3);
1615   std::advance(End, 4);
1616   IRSimilarityCandidate Cand2(3, 2, *Start, *End);
1617   if (Structure)
1618     return IRSimilarityCandidate::compareStructure(Cand1, Cand2);
1619   return IRSimilarityCandidate::isSimilar(Cand1, Cand2);
1620 }
1621 
1622 // Checks that two adds with commuted operands are considered to be the same
1623 // instructions.
1624 TEST(IRSimilarityCandidate, CheckIdenticalInstructions) {
1625   StringRef ModuleString = R"(
1626                           define i32 @f(i32 %a, i32 %b) {
1627                           bb0:
1628                              %0 = add i32 %a, %b
1629                              %1 = add i32 %b, %a
1630                              ret i32 0
1631                           })";
1632   LLVMContext Context;
1633   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1634 
1635   std::vector<IRInstructionData *> InstrList;
1636   std::vector<unsigned> UnsignedVec;
1637 
1638   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1639   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1640   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1641   getVectors(*M, Mapper, InstrList, UnsignedVec);
1642 
1643   // Check to make sure that we have a long enough region.
1644   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(3));
1645   // Check that the instructions were added correctly to both vectors.
1646   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1647 
1648   std::vector<IRInstructionData *>::iterator Start, End;
1649   Start = InstrList.begin();
1650   End = InstrList.begin();
1651   std::advance(End, 1);
1652   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
1653   IRSimilarityCandidate Cand2(0, 2, *Start, *End);
1654 
1655   ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1656 }
1657 
1658 // Checks that comparison instructions are found to be similar instructions
1659 // when the operands are flipped and the predicate is also swapped.
1660 TEST(IRSimilarityCandidate, PredicateIsomorphism) {
1661   StringRef ModuleString = R"(
1662                           define i32 @f(i32 %a, i32 %b) {
1663                           bb0:
1664                              %0 = icmp sgt i32 %a, %b
1665                              %1 = add i32 %b, %a
1666                              br label %bb1
1667                           bb1:
1668                              %2 = icmp slt i32 %a, %b
1669                              %3 = add i32 %a, %b
1670                              ret i32 0
1671                           })";
1672   LLVMContext Context;
1673   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1674 
1675   std::vector<IRInstructionData *> InstrList;
1676   std::vector<unsigned> UnsignedVec;
1677 
1678   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1679   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1680   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1681   getVectors(*M, Mapper, InstrList, UnsignedVec);
1682 
1683   ASSERT_TRUE(InstrList.size() > 5);
1684   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1685 
1686   std::vector<IRInstructionData *>::iterator Start, End;
1687   Start = InstrList.begin();
1688   End = InstrList.begin();
1689 
1690   std::advance(End, 1);
1691   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
1692 
1693   Start = InstrList.begin();
1694   End = InstrList.begin();
1695 
1696   std::advance(Start, 3);
1697   std::advance(End, 4);
1698   IRSimilarityCandidate Cand2(3, 2, *Start, *End);
1699 
1700   ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1701 }
1702 
1703 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1704 // are able to differentiate between instructions that have different opcodes.
1705 TEST(IRSimilarityCandidate, CheckRegionsDifferentInstruction) {
1706   StringRef ModuleString = R"(
1707                           define i32 @f(i32 %a, i32 %b) {
1708                           bb0:
1709                              %0 = add i32 %a, %b
1710                              %1 = add i32 %b, %a
1711                              ret i32 0
1712                           bb1:
1713                              %2 = sub i32 %a, %b
1714                              %3 = add i32 %b, %a
1715                              ret i32 0
1716                           })";
1717   LLVMContext Context;
1718   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1719 
1720   std::vector<IRInstructionData *> InstrList;
1721   std::vector<unsigned> UnsignedVec;
1722 
1723   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1724   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1725   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1726   getVectors(*M, Mapper, InstrList, UnsignedVec);
1727 
1728   // Check to make sure that we have a long enough region.
1729   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1730   // Check that the instructions were added correctly to both vectors.
1731   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1732 
1733   ASSERT_FALSE(longSimCandCompare(InstrList));
1734 }
1735 
1736 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1737 // are able to differentiate between instructions that have different types.
1738 TEST(IRSimilarityCandidate, CheckRegionsDifferentTypes) {
1739   StringRef ModuleString = R"(
1740                           define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
1741                           bb0:
1742                              %0 = add i32 %a, %b
1743                              %1 = add i32 %b, %a
1744                              ret i32 0
1745                           bb1:
1746                              %2 = add i64 %c, %d
1747                              %3 = add i64 %d, %c
1748                              ret i32 0
1749                           })";
1750   LLVMContext Context;
1751   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1752 
1753   std::vector<IRInstructionData *> InstrList;
1754   std::vector<unsigned> UnsignedVec;
1755 
1756   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1757   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1758   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1759   getVectors(*M, Mapper, InstrList, UnsignedVec);
1760 
1761   // Check to make sure that we have a long enough region.
1762   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1763   // Check that the instructions were added correctly to both vectors.
1764   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1765 
1766   ASSERT_FALSE(longSimCandCompare(InstrList));
1767 }
1768 
1769 // Check that debug instructions do not impact similarity. They are marked as
1770 // invisible.
1771 TEST(IRSimilarityCandidate, IdenticalWithDebug) {
1772   StringRef ModuleString = R"(
1773                           define i32 @f(i32 %a, i32 %b) {
1774                           bb0:
1775                              %0 = add i32 %a, %b
1776                              call void @llvm.dbg.value(metadata !0)
1777                              %1 = add i32 %b, %a
1778                              ret i32 0
1779                           bb1:
1780                              %2 = add i32 %a, %b
1781                              call void @llvm.dbg.value(metadata !1)
1782                              %3 = add i32 %b, %a
1783                              ret i32 0
1784                           bb2:
1785                              %4 = add i32 %a, %b
1786                              %5 = add i32 %b, %a
1787                              ret i32 0
1788                           }
1789 
1790                           declare void @llvm.dbg.value(metadata)
1791                           !0 = distinct !{!"test\00", i32 10}
1792                           !1 = distinct !{!"test\00", i32 11})";
1793   LLVMContext Context;
1794   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1795 
1796   std::vector<IRInstructionData *> InstrList;
1797   std::vector<unsigned> UnsignedVec;
1798 
1799   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1800   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1801   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1802   getVectors(*M, Mapper, InstrList, UnsignedVec);
1803 
1804   // Check to make sure that we have a long enough region.
1805   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(9));
1806   // Check that the instructions were added correctly to both vectors.
1807   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1808 
1809   ASSERT_TRUE(longSimCandCompare(InstrList));
1810 }
1811 
1812 // Checks that IRSimilarityCandidates that include illegal instructions, are not
1813 // considered to be the same set of instructions.  In these sets of instructions
1814 // the allocas are illegal.
1815 TEST(IRSimilarityCandidate, IllegalInCandidate) {
1816   StringRef ModuleString = R"(
1817                           define i32 @f(i32 %a, i32 %b) {
1818                           bb0:
1819                              %0 = add i32 %a, %b
1820                              %1 = add i32 %a, %b
1821                              %2 = alloca i32
1822                              ret i32 0
1823                           bb1:
1824                              %3 = add i32 %a, %b
1825                              %4 = add i32 %a, %b
1826                              %5 = alloca i32
1827                              ret i32 0
1828                           })";
1829   LLVMContext Context;
1830   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1831 
1832   std::vector<IRInstructionData *> InstrList;
1833   std::vector<unsigned> UnsignedVec;
1834 
1835   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1836   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1837   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1838   getVectors(*M, Mapper, InstrList, UnsignedVec);
1839 
1840   // Check to make sure that we have a long enough region.
1841   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1842   // Check that the instructions were added correctly to both vectors.
1843   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1844 
1845   std::vector<IRInstructionData *>::iterator Start, End;
1846 
1847   Start = InstrList.begin();
1848   End = InstrList.begin();
1849 
1850   std::advance(End, 2);
1851   IRSimilarityCandidate Cand1(0, 3, *Start, *End);
1852 
1853   Start = InstrList.begin();
1854   End = InstrList.begin();
1855 
1856   std::advance(Start, 3);
1857   std::advance(End, 5);
1858   IRSimilarityCandidate Cand2(3, 3, *Start, *End);
1859   ASSERT_FALSE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1860 }
1861 
1862 // Checks that different structure, in this case, where we introduce a new
1863 // needed input in one region, is recognized as different.
1864 TEST(IRSimilarityCandidate, DifferentStructure) {
1865   StringRef ModuleString = R"(
1866                           define i32 @f(i32 %a, i32 %b) {
1867                           bb0:
1868                              %0 = add i32 %a, %b
1869                              %1 = add i32 %b, %a
1870                              ret i32 0
1871                           bb1:
1872                              %2 = add i32 %a, %b
1873                              %3 = add i32 %b, %0
1874                              ret i32 0
1875                           })";
1876   LLVMContext Context;
1877   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1878 
1879   std::vector<IRInstructionData *> InstrList;
1880   std::vector<unsigned> UnsignedVec;
1881 
1882   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1883   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1884   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1885   getVectors(*M, Mapper, InstrList, UnsignedVec);
1886 
1887   // Check to make sure that we have a long enough region.
1888   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1889   // Check that the instructions were added correctly to both vectors.
1890   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1891 
1892   ASSERT_FALSE(longSimCandCompare(InstrList, true));
1893 }
1894 
1895 // Checks that comparison instructions are found to have the same structure
1896 // when the operands are flipped and the predicate is also swapped.
1897 TEST(IRSimilarityCandidate, PredicateIsomorphismStructure) {
1898   StringRef ModuleString = R"(
1899                           define i32 @f(i32 %a, i32 %b) {
1900                           bb0:
1901                              %0 = icmp sgt i32 %a, %b
1902                              %1 = add i32 %a, %b
1903                              br label %bb1
1904                           bb1:
1905                              %2 = icmp slt i32 %b, %a
1906                              %3 = add i32 %a, %b
1907                              ret i32 0
1908                           })";
1909   LLVMContext Context;
1910   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1911 
1912   std::vector<IRInstructionData *> InstrList;
1913   std::vector<unsigned> UnsignedVec;
1914 
1915   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1916   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1917   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1918   getVectors(*M, Mapper, InstrList, UnsignedVec);
1919 
1920   ASSERT_TRUE(InstrList.size() > 5);
1921   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1922 
1923   ASSERT_TRUE(longSimCandCompare(InstrList, true));
1924 }
1925 
1926 // Checks that different predicates are counted as diferent.
1927 TEST(IRSimilarityCandidate, PredicateDifference) {
1928   StringRef ModuleString = R"(
1929                           define i32 @f(i32 %a, i32 %b) {
1930                           bb0:
1931                              %0 = icmp sge i32 %a, %b
1932                              %1 = add i32 %b, %a
1933                              br label %bb1
1934                           bb1:
1935                              %2 = icmp slt i32 %b, %a
1936                              %3 = add i32 %a, %b
1937                              ret i32 0
1938                           })";
1939   LLVMContext Context;
1940   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1941 
1942   std::vector<IRInstructionData *> InstrList;
1943   std::vector<unsigned> UnsignedVec;
1944 
1945   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1946   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1947   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1948   getVectors(*M, Mapper, InstrList, UnsignedVec);
1949 
1950   ASSERT_TRUE(InstrList.size() > 5);
1951   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1952 
1953   ASSERT_FALSE(longSimCandCompare(InstrList));
1954 }
1955 
1956 // Checks that the same structure is recognized between two candidates. The
1957 // items %a and %b are used in the same way in both sets of instructions.
1958 TEST(IRSimilarityCandidate, SameStructure) {
1959   StringRef ModuleString = R"(
1960                           define i32 @f(i32 %a, i32 %b) {
1961                           bb0:
1962                              %0 = add i32 %a, %b
1963                              %1 = sub i32 %b, %a
1964                              ret i32 0
1965                           bb1:
1966                              %2 = add i32 %a, %b
1967                              %3 = sub i32 %b, %a
1968                              ret i32 0
1969                           })";
1970   LLVMContext Context;
1971   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1972 
1973   std::vector<IRInstructionData *> InstrList;
1974   std::vector<unsigned> UnsignedVec;
1975 
1976   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1977   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1978   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1979   getVectors(*M, Mapper, InstrList, UnsignedVec);
1980 
1981   // Check to make sure that we have a long enough region.
1982   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1983   // Check that the instructions were added correctly to both vectors.
1984   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1985 
1986   ASSERT_TRUE(longSimCandCompare(InstrList, true));
1987 }
1988 
1989 // Checks that the canonical numbering between two candidates matches the found
1990 // mapping between two candidates.
1991 TEST(IRSimilarityCandidate, CanonicalNumbering) {
1992   StringRef ModuleString = R"(
1993                           define i32 @f(i32 %a, i32 %b) {
1994                           bb0:
1995                              %0 = add i32 %a, %b
1996                              %1 = sub i32 %b, %a
1997                              ret i32 0
1998                           bb1:
1999                              %2 = add i32 %a, %b
2000                              %3 = sub i32 %b, %a
2001                              ret i32 0
2002                           })";
2003   LLVMContext Context;
2004   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2005 
2006   std::vector<IRInstructionData *> InstrList;
2007   std::vector<unsigned> UnsignedVec;
2008 
2009   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2010   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2011   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2012   getVectors(*M, Mapper, InstrList, UnsignedVec);
2013 
2014   // Check to make sure that we have a long enough region.
2015   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2016   // Check that the instructions were added correctly to both vectors.
2017   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
2018 
2019   std::vector<IRInstructionData *>::iterator Start, End;
2020 
2021   Start = InstrList.begin();
2022   End = InstrList.begin();
2023 
2024   std::advance(End, 1);
2025   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
2026 
2027   Start = InstrList.begin();
2028   End = InstrList.begin();
2029 
2030   std::advance(Start, 3);
2031   std::advance(End, 4);
2032   IRSimilarityCandidate Cand2(3, 2, *Start, *End);
2033   DenseMap<unsigned, DenseSet<unsigned>> Mapping1;
2034   DenseMap<unsigned, DenseSet<unsigned>> Mapping2;
2035   ASSERT_TRUE(IRSimilarityCandidate::compareStructure(Cand1, Cand2, Mapping1,
2036                                                       Mapping2));
2037   IRSimilarityCandidate::createCanonicalMappingFor(Cand1);
2038   Cand2.createCanonicalRelationFrom(Cand1, Mapping1, Mapping2);
2039 
2040   for (std::pair<unsigned, DenseSet<unsigned>> &P : Mapping2) {
2041     unsigned Source = P.first;
2042 
2043     ASSERT_TRUE(Cand2.getCanonicalNum(Source).hasValue());
2044     unsigned Canon = *Cand2.getCanonicalNum(Source);
2045     ASSERT_TRUE(Cand1.fromCanonicalNum(Canon).hasValue());
2046     unsigned Dest = *Cand1.fromCanonicalNum(Canon);
2047 
2048     DenseSet<unsigned>::iterator It = P.second.find(Dest);
2049     ASSERT_NE(It, P.second.end());
2050   }
2051 }
2052 
2053 // Checks that the same structure is recognized between two candidates. While
2054 // the input names are reversed, they still perform the same overall operation.
2055 TEST(IRSimilarityCandidate, DifferentNameSameStructure) {
2056   StringRef ModuleString = R"(
2057                           define i32 @f(i32 %a, i32 %b) {
2058                           bb0:
2059                              %0 = add i32 %a, %b
2060                              %1 = add i32 %b, %a
2061                              ret i32 0
2062                           bb1:
2063                              %2 = add i32 %b, %a
2064                              %3 = add i32 %a, %b
2065                              ret i32 0
2066                           })";
2067   LLVMContext Context;
2068   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2069 
2070   std::vector<IRInstructionData *> InstrList;
2071   std::vector<unsigned> UnsignedVec;
2072 
2073   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2074   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2075   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2076   getVectors(*M, Mapper, InstrList, UnsignedVec);
2077 
2078   // Check to make sure that we have a long enough region.
2079   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2080   // Check that the instructions were added correctly to both vectors.
2081   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2082 
2083   ASSERT_TRUE(longSimCandCompare(InstrList, true));
2084 }
2085 
2086 // Checks that two sets of identical instructions are found to be the same.
2087 // Both sequences of adds have the same operand ordering, and the same
2088 // instructions, making them strcturally equivalent.
2089 TEST(IRSimilarityIdentifier, IdentitySimilarity) {
2090   StringRef ModuleString = R"(
2091                           define i32 @f(i32 %a, i32 %b) {
2092                           bb0:
2093                              %0 = add i32 %a, %b
2094                              %1 = sub i32 %b, %a
2095                              br label %bb1
2096                           bb1:
2097                              %2 = add i32 %a, %b
2098                              %3 = sub i32 %b, %a
2099                              ret i32 0
2100                           })";
2101   LLVMContext Context;
2102   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2103 
2104   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2105   getSimilarities(*M, SimilarityCandidates);
2106 
2107   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2108   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2109     ASSERT_TRUE(Cands.size() == 2);
2110     unsigned InstIdx = 0;
2111     for (IRSimilarityCandidate &Cand : Cands) {
2112       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2113       InstIdx += 3;
2114     }
2115   }
2116 }
2117 
2118 // Checks that incorrect sequences are not found as similar.  In this case,
2119 // we have different sequences of instructions.
2120 TEST(IRSimilarityIdentifier, InstructionDifference) {
2121   StringRef ModuleString = R"(
2122                           define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2123                           bb0:
2124                              %0 = sub i32 %a, %b
2125                              %1 = add i32 %b, %a
2126                              br label %bb1
2127                           bb1:
2128                              %2 = add i32 %c, %d
2129                              %3 = sub i32 %d, %c
2130                              ret i32 0
2131                           })";
2132   LLVMContext Context;
2133   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2134 
2135   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2136   getSimilarities(*M, SimilarityCandidates);
2137 
2138   ASSERT_TRUE(SimilarityCandidates.empty());
2139 }
2140 
2141 // This test checks to see whether we can detect similarity for commutative
2142 // instructions where the operands have been reversed.
2143 TEST(IRSimilarityIdentifier, CommutativeSimilarity) {
2144   StringRef ModuleString = R"(
2145                           define i32 @f(i32 %a, i32 %b) {
2146                           bb0:
2147                              %0 = add i32 %a, %b
2148                              %1 = add i32 %b, %a
2149                              br label %bb1
2150                           bb1:
2151                              %2 = add i32 %a, %b
2152                              %3 = add i32 %a, %b
2153                              ret i32 0
2154                           })";
2155   LLVMContext Context;
2156   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2157 
2158   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2159   getSimilarities(*M, SimilarityCandidates);
2160 
2161   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2162   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2163     ASSERT_TRUE(Cands.size() == 2);
2164     unsigned InstIdx = 0;
2165     for (IRSimilarityCandidate &Cand : Cands) {
2166       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2167       InstIdx += 3;
2168     }
2169   }
2170 }
2171 
2172 // This test checks to see whether we can detect different structure in
2173 // commutative instructions.  In this case, the second operand in the second
2174 // add is different.
2175 TEST(IRSimilarityIdentifier, NoCommutativeSimilarity) {
2176   StringRef ModuleString = R"(
2177                           define i32 @f(i32 %a, i32 %b) {
2178                           bb0:
2179                              %0 = add i32 %a, %b
2180                              %1 = add i32 %1, %b
2181                              br label %bb1
2182                           bb1:
2183                              %2 = add i32 %a, %b
2184                              %3 = add i32 %2, %a
2185                              ret i32 0
2186                           })";
2187   LLVMContext Context;
2188   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2189 
2190   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2191   getSimilarities(*M, SimilarityCandidates);
2192 
2193   ASSERT_TRUE(SimilarityCandidates.size() == 0);
2194 }
2195 
2196 // Check that we are not finding similarity in non commutative
2197 // instructions.  That is, while the instruction and operands used are the same
2198 // in the two subtraction sequences, they are in a different order, and cannot
2199 // be counted as the same since a subtraction is not commutative.
2200 TEST(IRSimilarityIdentifier, NonCommutativeDifference) {
2201   StringRef ModuleString = R"(
2202                           define i32 @f(i32 %a, i32 %b) {
2203                           bb0:
2204                              %0 = sub i32 %a, %b
2205                              %1 = sub i32 %b, %a
2206                              br label %bb1
2207                           bb1:
2208                              %2 = sub i32 %a, %b
2209                              %3 = sub i32 %a, %b
2210                              ret i32 0
2211                           })";
2212   LLVMContext Context;
2213   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2214 
2215   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2216   getSimilarities(*M, SimilarityCandidates);
2217 
2218   ASSERT_TRUE(SimilarityCandidates.empty());
2219 }
2220 
2221 // Check that we find similarity despite changing the register names.
2222 TEST(IRSimilarityIdentifier, MappingSimilarity) {
2223   StringRef ModuleString = R"(
2224                           define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2225                           bb0:
2226                              %0 = add i32 %a, %b
2227                              %1 = sub i32 %b, %a
2228                              br label %bb1
2229                           bb1:
2230                              %2 = add i32 %c, %d
2231                              %3 = sub i32 %d, %c
2232                              ret i32 0
2233                           })";
2234   LLVMContext Context;
2235   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2236 
2237   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2238   getSimilarities(*M, SimilarityCandidates);
2239 
2240   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2241   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2242     ASSERT_TRUE(Cands.size() == 2);
2243     unsigned InstIdx = 0;
2244     for (IRSimilarityCandidate &Cand : Cands) {
2245       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2246       InstIdx += 3;
2247     }
2248   }
2249 }
2250 
2251 // Check that we find instances of swapped predicate isomorphism.  That is,
2252 // for predicates that can be flipped, e.g. greater than to less than,
2253 // we can identify that instances of these different literal predicates, but are
2254 // the same within a single swap can be found.
2255 TEST(IRSimilarityIdentifier, PredicateIsomorphism) {
2256   StringRef ModuleString = R"(
2257                           define i32 @f(i32 %a, i32 %b) {
2258                           bb0:
2259                              %0 = add i32 %a, %b
2260                              %1 = icmp sgt i32 %b, %a
2261                              br label %bb1
2262                           bb1:
2263                              %2 = add i32 %a, %b
2264                              %3 = icmp slt i32 %a, %b
2265                              ret i32 0
2266                           })";
2267   LLVMContext Context;
2268   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2269 
2270   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2271   getSimilarities(*M, SimilarityCandidates);
2272 
2273   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2274   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2275     ASSERT_TRUE(Cands.size() == 2);
2276     unsigned InstIdx = 0;
2277     for (IRSimilarityCandidate &Cand : Cands) {
2278       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2279       InstIdx += 3;
2280     }
2281   }
2282 }
2283 
2284 // Checks that constants are detected as the same operand in each use in the
2285 // sequences of instructions.  Also checks that we can find structural
2286 // equivalence using constants.  In this case the 1 has the same use pattern as
2287 // %a.
2288 TEST(IRSimilarityIdentifier, ConstantMappingSimilarity) {
2289   StringRef ModuleString = R"(
2290                           define i32 @f(i32 %a, i32 %b) {
2291                           bb0:
2292                              %0 = add i32 1, %b
2293                              %1 = icmp sgt i32 %b, 1
2294                              br label %bb1
2295                           bb1:
2296                              %2 = add i32 %a, %b
2297                              %3 = icmp sgt i32 %b, %a
2298                              ret i32 0
2299                           })";
2300   LLVMContext Context;
2301   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2302 
2303   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2304   getSimilarities(*M, SimilarityCandidates);
2305 
2306   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2307   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2308     ASSERT_TRUE(Cands.size() == 2);
2309     unsigned InstIdx = 0;
2310     for (IRSimilarityCandidate &Cand : Cands) {
2311       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2312       InstIdx += 3;
2313     }
2314   }
2315 }
2316 
2317 // Check that constants are uniquely identified. i.e. two different constants
2318 // are not considered the same.  This means that this should not find any
2319 // structural similarity.
2320 TEST(IRSimilarityIdentifier, ConstantMappingDifference) {
2321   StringRef ModuleString = R"(
2322                           define i32 @f(i32 %a, i32 %b) {
2323                           bb0:
2324                              %0 = add i32 1, %b
2325                              %1 = icmp sgt i32 %b, 2
2326                              br label %bb1
2327                           bb1:
2328                              %2 = add i32 %a, %b
2329                              %3 = icmp slt i32 %a, %b
2330                              ret i32 0
2331                           })";
2332   LLVMContext Context;
2333   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2334 
2335   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2336   getSimilarities(*M, SimilarityCandidates);
2337 
2338   ASSERT_TRUE(SimilarityCandidates.empty());
2339 }
2340