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