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 // Checks that a PHINode is mapped to be legal.
761 TEST(IRInstructionMapper, PhiLegal) {
762   StringRef ModuleString = R"(
763                           define i32 @f(i32 %a, i32 %b) {
764                           bb0:
765                              %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
766                              %1 = add i32 %a, %b
767                              ret i32 0
768                           bb1:
769                              ret i32 1
770                           })";
771   LLVMContext Context;
772   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
773 
774   std::vector<IRInstructionData *> InstrList;
775   std::vector<unsigned> UnsignedVec;
776 
777   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
778   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
779   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
780   Mapper.InstClassifier.EnableBranches = true;
781   Mapper.initializeForBBs(*M);
782   getVectors(*M, Mapper, InstrList, UnsignedVec);
783 
784   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
785   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
786 }
787 
788 // Checks that a PHINode is mapped to be legal.
789 TEST(IRInstructionMapper, PhiIllegal) {
790   StringRef ModuleString = R"(
791                           define i32 @f(i32 %a, i32 %b) {
792                           bb0:
793                              %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
794                              %1 = add i32 %a, %b
795                              ret i32 0
796                           bb1:
797                              ret i32 1
798                           })";
799   LLVMContext Context;
800   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
801 
802   std::vector<IRInstructionData *> InstrList;
803   std::vector<unsigned> UnsignedVec;
804 
805   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
806   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
807   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
808   Mapper.initializeForBBs(*M);
809   getVectors(*M, Mapper, InstrList, UnsignedVec);
810 
811   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
812   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
813 }
814 
815 // In most cases, the illegal instructions we are collecting don't require any
816 // sort of setup.  In these cases, we can just only have illegal instructions,
817 // and the mapper will create 0 length vectors, and we can check that.
818 
819 // In cases where we have legal instructions needed to set up the illegal
820 // instruction, to check illegal instructions are assigned unsigned integers
821 // from the maximum value decreasing to 0, it will be greater than a legal
822 // instruction that comes after.  So to check that we have an illegal
823 // instruction, we place a legal instruction after an illegal instruction, and
824 // check that the illegal unsigned integer is greater than the unsigned integer
825 // of the legal instruction.
826 
827 // Checks that an alloca instruction is mapped to be illegal.
828 TEST(IRInstructionMapper, AllocaIllegal) {
829   StringRef ModuleString = R"(
830                           define i32 @f(i32 %a, i32 %b) {
831                           bb0:
832                              %0 = alloca i32
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>(0));
848 }
849 
850 // Checks that an getelementptr instruction is mapped to be legal.  And that
851 // the operands in getelementpointer instructions are the exact same after the
852 // first element operand, which only requires the same type.
853 TEST(IRInstructionMapper, GetElementPtrSameEndOperands) {
854   StringRef ModuleString = R"(
855     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
856     %struct.ST = type { i32, double, %struct.RT }
857     define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
858     bb0:
859        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
860        %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 0
861        ret i32 0
862     })";
863   LLVMContext Context;
864   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
865 
866   std::vector<IRInstructionData *> InstrList;
867   std::vector<unsigned> UnsignedVec;
868 
869   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
870   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
871   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
872   getVectors(*M, Mapper, InstrList, UnsignedVec);
873 
874   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
875   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
876   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
877 }
878 
879 // Check that when the operands in getelementpointer instructions are not the
880 // exact same after the first element operand, the instructions are mapped to
881 // different values.
882 TEST(IRInstructionMapper, GetElementPtrDifferentEndOperands) {
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, i64 %a, i64 %b) {
887     bb0:
888        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
889        %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 2
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 are not the
909 // same initial base type, each instruction is mapped to a different value.
910 TEST(IRInstructionMapper, GetElementPtrDifferentBaseType) {
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
917        %1 = getelementptr inbounds %struct.RT, %struct.RT* %r, i64 %b
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 // Check that when the operands in getelementpointer instructions do not have
937 // the same inbounds modifier, they are not counted as the same.
938 TEST(IRInstructionMapper, GetElementPtrDifferentInBounds) {
939   StringRef ModuleString = R"(
940     %struct.RT = type { i8, [10 x [20 x i32]], i8 }
941     %struct.ST = type { i32, double, %struct.RT }
942     define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
943     bb0:
944        %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
945        %1 = getelementptr %struct.ST, %struct.ST* %s, i64 %b, i32 0
946        ret i32 0
947     })";
948   LLVMContext Context;
949   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
950 
951   std::vector<IRInstructionData *> InstrList;
952   std::vector<unsigned> UnsignedVec;
953 
954   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
955   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
956   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
957   getVectors(*M, Mapper, InstrList, UnsignedVec);
958 
959   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
960   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
961   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
962 }
963 
964 // Checks that indirect call instructions are mapped to be illegal when it is
965 // specified to disallow them.
966 TEST(IRInstructionMapper, CallsIllegalIndirect) {
967   StringRef ModuleString = R"(
968                           define i32 @f(void()* %func) {
969                           bb0:
970                              call void %func()
971                              ret i32 0
972                           })";
973   LLVMContext Context;
974   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
975 
976   std::vector<IRInstructionData *> InstrList;
977   std::vector<unsigned> UnsignedVec;
978 
979   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
980   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
981   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
982   Mapper.InstClassifier.EnableIndirectCalls = false;
983   getVectors(*M, Mapper, InstrList, UnsignedVec);
984 
985   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
986   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
987 }
988 
989 // Checks that indirect call instructions are mapped to be legal when it is not
990 // specified to disallow them.
991 TEST(IRInstructionMapper, CallsLegalIndirect) {
992   StringRef ModuleString = R"(
993                           define i32 @f(void()* %func) {
994                           bb0:
995                              call void %func()
996                              call void %func()
997                              ret i32 0
998                           })";
999   LLVMContext Context;
1000   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1001 
1002   std::vector<IRInstructionData *> InstrList;
1003   std::vector<unsigned> UnsignedVec;
1004 
1005   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1006   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1007   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1008   Mapper.InstClassifier.EnableIndirectCalls = true;
1009   getVectors(*M, Mapper, InstrList, UnsignedVec);
1010 
1011   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1012   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1013 }
1014 
1015 // Checks that a call instruction is mapped to be legal.  Here we check that
1016 // a call with the same name, and same types are mapped to the same
1017 // value.
1018 TEST(IRInstructionMapper, CallsSameTypeSameName) {
1019   StringRef ModuleString = R"(
1020                           declare i32 @f1(i32, i32)
1021                           define i32 @f(i32 %a, i32 %b) {
1022                           bb0:
1023                              %0 = call i32 @f1(i32 %a, i32 %b)
1024                              %1 = call i32 @f1(i32 %a, i32 %b)
1025                              ret i32 0
1026                           })";
1027   LLVMContext Context;
1028   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1029 
1030   std::vector<IRInstructionData *> InstrList;
1031   std::vector<unsigned> UnsignedVec;
1032 
1033   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1034   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1035   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1036   getVectors(*M, Mapper, InstrList, UnsignedVec);
1037 
1038   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1039   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1040   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
1041 }
1042 
1043 // Here we check that a calls with different names, but the same arguments types
1044 // are mapped to different value when specified that the name must match.
1045 TEST(IRInstructionMapper, CallsSameArgTypeDifferentNameDisallowed) {
1046   StringRef ModuleString = R"(
1047                           declare i32 @f1(i32, i32)
1048                           declare i32 @f2(i32, i32)
1049                           define i32 @f(i32 %a, i32 %b) {
1050                           bb0:
1051                              %0 = call i32 @f1(i32 %a, i32 %b)
1052                              %1 = call i32 @f2(i32 %a, i32 %b)
1053                              ret i32 0
1054                           })";
1055   LLVMContext Context;
1056   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1057 
1058   std::vector<IRInstructionData *> InstrList;
1059   std::vector<unsigned> UnsignedVec;
1060 
1061   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1062   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1063   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1064   Mapper.EnableMatchCallsByName = true;
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 a calls with different names, but the same arguments types
1073 // are mapped to the same value when it is not specifed that they must match.
1074 TEST(IRInstructionMapper, CallsSameArgTypeDifferentName) {
1075   StringRef ModuleString = R"(
1076                           declare i32 @f1(i32, i32)
1077                           declare i32 @f2(i32, i32)
1078                           define i32 @f(i32 %a, i32 %b) {
1079                           bb0:
1080                              %0 = call i32 @f1(i32 %a, i32 %b)
1081                              %1 = call i32 @f2(i32 %a, i32 %b)
1082                              ret i32 0
1083                           })";
1084   LLVMContext Context;
1085   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1086 
1087   std::vector<IRInstructionData *> InstrList;
1088   std::vector<unsigned> UnsignedVec;
1089 
1090   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1091   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1092   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1093   Mapper.EnableMatchCallsByName = false;
1094   getVectors(*M, Mapper, InstrList, UnsignedVec);
1095 
1096   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1097   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1098   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
1099 }
1100 
1101 // Here we check that a calls with different names, and different arguments
1102 // types are mapped to different value.
1103 TEST(IRInstructionMapper, CallsDifferentArgTypeDifferentName) {
1104   StringRef ModuleString = R"(
1105                           declare i32 @f1(i32, i32)
1106                           declare i32 @f2(i32)
1107                           define i32 @f(i32 %a, i32 %b) {
1108                           bb0:
1109                              %0 = call i32 @f1(i32 %a, i32 %b)
1110                              %1 = call i32 @f2(i32 %a)
1111                              ret i32 0
1112                           })";
1113   LLVMContext Context;
1114   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1115 
1116   std::vector<IRInstructionData *> InstrList;
1117   std::vector<unsigned> UnsignedVec;
1118 
1119   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1120   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1121   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1122   getVectors(*M, Mapper, InstrList, UnsignedVec);
1123 
1124   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1125   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1126   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1127 }
1128 
1129 // Here we check that calls with different names, and different return
1130 // types are mapped to different value.
1131 TEST(IRInstructionMapper, CallsDifferentReturnTypeDifferentName) {
1132   StringRef ModuleString = R"(
1133                           declare i64 @f1(i32, i32)
1134                           declare i32 @f2(i32, i32)
1135                           define i32 @f(i32 %a, i32 %b) {
1136                           bb0:
1137                              %0 = call i64 @f1(i32 %a, i32 %b)
1138                              %1 = call i32 @f2(i32 %a, i32 %b)
1139                              ret i32 0
1140                           })";
1141   LLVMContext Context;
1142   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1143 
1144   std::vector<IRInstructionData *> InstrList;
1145   std::vector<unsigned> UnsignedVec;
1146 
1147   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1148   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1149   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1150   getVectors(*M, Mapper, InstrList, UnsignedVec);
1151 
1152   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1153   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1154   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1155 }
1156 
1157 // Here we check that calls with the same name, types, and parameters map to the
1158 // same unsigned integer.
1159 TEST(IRInstructionMapper, CallsSameParameters) {
1160   StringRef ModuleString = R"(
1161                           declare i32 @f1(i32, i32)
1162                           define i32 @f(i32 %a, i32 %b) {
1163                           bb0:
1164                              %0 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1165                              %1 = tail call fastcc i32 @f1(i32 %a, i32 %b)
1166                              ret i32 0
1167                           })";
1168   LLVMContext Context;
1169   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1170 
1171   std::vector<IRInstructionData *> InstrList;
1172   std::vector<unsigned> UnsignedVec;
1173 
1174   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1175   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1176   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1177   getVectors(*M, Mapper, InstrList, UnsignedVec);
1178 
1179   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1180   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1181   ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
1182 }
1183 
1184 // Here we check that calls with different tail call settings are mapped to
1185 // different values.
1186 TEST(IRInstructionMapper, CallsDifferentTails) {
1187   StringRef ModuleString = R"(
1188                           declare i32 @f1(i32, i32)
1189                           define i32 @f(i32 %a, i32 %b) {
1190                           bb0:
1191                              %0 = tail call i32 @f1(i32 %a, i32 %b)
1192                              %1 = call i32 @f1(i32 %a, i32 %b)
1193                              ret i32 0
1194                           })";
1195   LLVMContext Context;
1196   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1197 
1198   std::vector<IRInstructionData *> InstrList;
1199   std::vector<unsigned> UnsignedVec;
1200 
1201   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1202   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1203   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1204   getVectors(*M, Mapper, InstrList, UnsignedVec);
1205 
1206   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1207   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1208   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1209 }
1210 
1211 // Here we check that calls with different calling convention settings are
1212 // mapped to different values.
1213 TEST(IRInstructionMapper, CallsDifferentCallingConventions) {
1214   StringRef ModuleString = R"(
1215                           declare i32 @f1(i32, i32)
1216                           define i32 @f(i32 %a, i32 %b) {
1217                           bb0:
1218                              %0 = call fastcc i32 @f1(i32 %a, i32 %b)
1219                              %1 = call i32 @f1(i32 %a, i32 %b)
1220                              ret i32 0
1221                           })";
1222   LLVMContext Context;
1223   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1224 
1225   std::vector<IRInstructionData *> InstrList;
1226   std::vector<unsigned> UnsignedVec;
1227 
1228   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1229   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1230   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1231   getVectors(*M, Mapper, InstrList, UnsignedVec);
1232 
1233   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1234   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1235   ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
1236 }
1237 
1238 // Checks that an invoke instruction is mapped to be illegal. Invoke
1239 // instructions are considered to be illegal because of the change in the
1240 // control flow that is currently not recognized.
1241 TEST(IRInstructionMapper, InvokeIllegal) {
1242   StringRef ModuleString = R"(
1243                           define i32 @f(i8 *%gep1, i32 %b) {
1244                           then:
1245                             invoke i32 undef(i8* undef)
1246                                to label %invoke unwind label %lpad
1247 
1248                           invoke:
1249                             unreachable
1250 
1251                           lpad:
1252                             landingpad { i8*, i32 }
1253                                catch i8* null
1254                             unreachable
1255                           })";
1256   LLVMContext Context;
1257   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1258 
1259   std::vector<IRInstructionData *> InstrList;
1260   std::vector<unsigned> UnsignedVec;
1261 
1262   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1263   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1264   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1265   getVectors(*M, Mapper, InstrList, UnsignedVec);
1266 
1267   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1268   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1269 }
1270 
1271 // Checks that an callbr instructions are considered to be illegal.  Callbr
1272 // instructions are considered to be illegal because of the change in the
1273 // control flow that is currently not recognized.
1274 TEST(IRInstructionMapper, CallBrInstIllegal) {
1275   StringRef ModuleString = R"(
1276   define void @test() {
1277     fail:
1278       ret void
1279   }
1280 
1281   define i32 @f(i32 %a, i32 %b) {
1282       bb0:
1283         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]
1284       fail:
1285         ret i32 0
1286       normal:
1287         ret i32 0
1288   })";
1289   LLVMContext Context;
1290   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1291 
1292   std::vector<IRInstructionData *> InstrList;
1293   std::vector<unsigned> UnsignedVec;
1294 
1295   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1296   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1297   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1298   getVectors(*M, Mapper, InstrList, UnsignedVec);
1299 
1300   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1301   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1302 }
1303 
1304 // Checks that an debuginfo intrinsics are mapped to be invisible.  Since they
1305 // do not semantically change the program, they can be recognized as similar.
1306 TEST(IRInstructionMapper, DebugInfoInvisible) {
1307   StringRef ModuleString = R"(
1308                           define i32 @f(i32 %a, i32 %b) {
1309                           then:
1310                             %0 = add i32 %a, %b
1311                             call void @llvm.dbg.value(metadata !0)
1312                             %1 = add i32 %a, %b
1313                             ret i32 0
1314                           }
1315 
1316                           declare void @llvm.dbg.value(metadata)
1317                           !0 = distinct !{!"test\00", i32 10})";
1318   LLVMContext Context;
1319   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1320 
1321   std::vector<IRInstructionData *> InstrList;
1322   std::vector<unsigned> UnsignedVec;
1323 
1324   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1325   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1326   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1327   getVectors(*M, Mapper, InstrList, UnsignedVec);
1328 
1329   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1330   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
1331 }
1332 
1333 // The following are all exception handling intrinsics.  We do not currently
1334 // handle these instruction because they are very context dependent.
1335 
1336 // Checks that an eh.typeid.for intrinsic is mapped to be illegal.
1337 TEST(IRInstructionMapper, ExceptionHandlingTypeIdIllegal) {
1338   StringRef ModuleString = R"(
1339     @_ZTIi = external constant i8*
1340     define i32 @f() {
1341     then:
1342       %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
1343       ret i32 0
1344     }
1345 
1346     declare i32 @llvm.eh.typeid.for(i8*))";
1347   LLVMContext Context;
1348   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1349 
1350   std::vector<IRInstructionData *> InstrList;
1351   std::vector<unsigned> UnsignedVec;
1352 
1353   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1354   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1355   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1356   getVectors(*M, Mapper, InstrList, UnsignedVec);
1357 
1358   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1359   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1360 }
1361 
1362 // Checks that an eh.exceptioncode intrinsic is mapped to be illegal.
1363 TEST(IRInstructionMapper, ExceptionHandlingExceptionCodeIllegal) {
1364   StringRef ModuleString = R"(
1365     define i32 @f(i32 %a, i32 %b) {
1366     entry:
1367       %0 = catchswitch within none [label %__except] unwind to caller
1368 
1369     __except:
1370       %1 = catchpad within %0 [i8* null]
1371       catchret from %1 to label %__except
1372 
1373     then:
1374       %2 = call i32 @llvm.eh.exceptioncode(token %1)
1375       ret i32 0
1376     }
1377 
1378     declare i32 @llvm.eh.exceptioncode(token))";
1379   LLVMContext Context;
1380   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1381 
1382   std::vector<IRInstructionData *> InstrList;
1383   std::vector<unsigned> UnsignedVec;
1384 
1385   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1386   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1387   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1388   getVectors(*M, Mapper, InstrList, UnsignedVec);
1389 
1390   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1391   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1392 }
1393 
1394 // Checks that an eh.unwind intrinsic is mapped to be illegal.
1395 TEST(IRInstructionMapper, ExceptionHandlingUnwindIllegal) {
1396   StringRef ModuleString = R"(
1397                           define i32 @f(i32 %a, i32 %b) {
1398                           entry:
1399                             call void @llvm.eh.unwind.init()
1400                             ret i32 0
1401                           }
1402 
1403                           declare void @llvm.eh.unwind.init())";
1404   LLVMContext Context;
1405   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1406 
1407   std::vector<IRInstructionData *> InstrList;
1408   std::vector<unsigned> UnsignedVec;
1409 
1410   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1411   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1412   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1413   getVectors(*M, Mapper, InstrList, UnsignedVec);
1414 
1415   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1416   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1417 }
1418 
1419 // Checks that an eh.exceptionpointer intrinsic is mapped to be illegal.
1420 TEST(IRInstructionMapper, ExceptionHandlingExceptionPointerIllegal) {
1421   StringRef ModuleString = R"(
1422                           define i32 @f(i32 %a, i32 %b) {
1423                           entry:
1424                             %0 = call i8* @llvm.eh.exceptionpointer.p0i8(i32 0)
1425                             ret i32 0
1426                           }
1427 
1428                           declare i8* @llvm.eh.exceptionpointer.p0i8(i32))";
1429   LLVMContext Context;
1430   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1431 
1432   std::vector<IRInstructionData *> InstrList;
1433   std::vector<unsigned> UnsignedVec;
1434 
1435   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1436   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1437   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1438   getVectors(*M, Mapper, InstrList, UnsignedVec);
1439 
1440   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1441   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1442 }
1443 
1444 // Checks that a catchpad instruction is mapped to an illegal value.
1445 TEST(IRInstructionMapper, CatchpadIllegal) {
1446   StringRef ModuleString = R"(
1447     declare void @llvm.donothing() nounwind readnone
1448 
1449     define void @function() personality i8 3 {
1450       entry:
1451         invoke void @llvm.donothing() to label %normal unwind label %exception
1452       exception:
1453         %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1454       catchpad1:
1455         catchpad within %cs1 []
1456         br label %normal
1457       normal:
1458         ret void
1459   })";
1460   LLVMContext Context;
1461   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1462 
1463   std::vector<IRInstructionData *> InstrList;
1464   std::vector<unsigned> UnsignedVec;
1465 
1466   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1467   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1468   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1469   getVectors(*M, Mapper, InstrList, UnsignedVec);
1470 
1471   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1472   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1473 }
1474 
1475 // Checks that a cleanuppad instruction is mapped to an illegal value.
1476 TEST(IRInstructionMapper, CleanuppadIllegal) {
1477   StringRef ModuleString = R"(
1478     declare void @llvm.donothing() nounwind readnone
1479 
1480     define void @function() personality i8 3 {
1481       entry:
1482         invoke void @llvm.donothing() to label %normal unwind label %exception
1483       exception:
1484         %cs1 = catchswitch within none [label %catchpad1] unwind to caller
1485       catchpad1:
1486         %clean = cleanuppad within none []
1487         br label %normal
1488       normal:
1489         ret void
1490   })";
1491   LLVMContext Context;
1492   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1493 
1494   std::vector<IRInstructionData *> InstrList;
1495   std::vector<unsigned> UnsignedVec;
1496 
1497   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1498   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1499   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1500   getVectors(*M, Mapper, InstrList, UnsignedVec);
1501 
1502   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1503   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(0));
1504 }
1505 
1506 // The following three instructions are memory transfer and setting based, which
1507 // are considered illegal since is extra checking needed to handle the address
1508 // space checking.
1509 
1510 // Checks that a memset instruction is mapped to an illegal value when
1511 // specified.
1512 TEST(IRInstructionMapper, MemSetIllegal) {
1513   StringRef ModuleString = R"(
1514   declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1515 
1516   define i64 @function(i64 %x, i64 %z, i64 %n) {
1517   entry:
1518     %pool = alloca [59 x i64], align 4
1519     %tmp = bitcast [59 x i64]* %pool to i8*
1520     call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1521     %cmp3 = icmp eq i64 %n, 0
1522     %a = add i64 %x, %z
1523     %c = add i64 %x, %z
1524     ret i64 0
1525   })";
1526   LLVMContext Context;
1527   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1528 
1529   std::vector<IRInstructionData *> InstrList;
1530   std::vector<unsigned> UnsignedVec;
1531 
1532   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1533   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1534   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1535   Mapper.InstClassifier.EnableIntrinsics = false;
1536   getVectors(*M, Mapper, InstrList, UnsignedVec);
1537 
1538   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1539   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
1540   ASSERT_TRUE(UnsignedVec[2] < UnsignedVec[0]);
1541 }
1542 
1543 // Checks that a memcpy instruction is mapped to an illegal value  when
1544 // specified.
1545 TEST(IRInstructionMapper, MemCpyIllegal) {
1546   StringRef ModuleString = R"(
1547   declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1548 
1549   define i64 @function(i64 %x, i64 %z, i64 %n) {
1550   entry:
1551     %pool = alloca [59 x i64], align 4
1552     %tmp = bitcast [59 x i64]* %pool to i8*
1553     call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1554     %cmp3 = icmp eq i64 %n, 0
1555     %a = add i64 %x, %z
1556     %c = add i64 %x, %z
1557     ret i64 0
1558   })";
1559   LLVMContext Context;
1560   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1561 
1562   std::vector<IRInstructionData *> InstrList;
1563   std::vector<unsigned> UnsignedVec;
1564 
1565   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1566   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1567   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1568   Mapper.InstClassifier.EnableIntrinsics = false;
1569   getVectors(*M, Mapper, InstrList, UnsignedVec);
1570 
1571   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1572   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
1573   ASSERT_GT(UnsignedVec[2], UnsignedVec[3]);
1574   ASSERT_LT(UnsignedVec[2], UnsignedVec[0]);
1575 }
1576 
1577 // Checks that a memmove instruction is mapped to an illegal value  when
1578 // specified.
1579 TEST(IRInstructionMapper, MemMoveIllegal) {
1580   StringRef ModuleString = R"(
1581   declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1582 
1583   define i64 @function(i64 %x, i64 %z, i64 %n) {
1584   entry:
1585     %pool = alloca [59 x i64], align 4
1586     %tmp = bitcast [59 x i64]* %pool to i8*
1587     call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1588     %cmp3 = icmp eq i64 %n, 0
1589     %a = add i64 %x, %z
1590     %c = add i64 %x, %z
1591     ret i64 0
1592   })";
1593   LLVMContext Context;
1594   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1595 
1596   std::vector<IRInstructionData *> InstrList;
1597   std::vector<unsigned> UnsignedVec;
1598 
1599   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1600   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1601   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1602   Mapper.InstClassifier.EnableIntrinsics = false;
1603   getVectors(*M, Mapper, InstrList, UnsignedVec);
1604 
1605   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1606   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
1607   ASSERT_LT(UnsignedVec[2], UnsignedVec[0]);
1608 }
1609 
1610 // Checks that mem* instructions are mapped to an legal value when not
1611 // specified, and that all the intrinsics are marked differently.
1612 TEST(IRInstructionMapper, MemOpsLegal) {
1613   StringRef ModuleString = R"(
1614   declare void @llvm.memmove.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1615   declare void @llvm.memcpy.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1616   declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1)
1617 
1618   define i64 @function(i64 %x, i64 %z, i64 %n) {
1619   entry:
1620     %pool = alloca [59 x i64], align 4
1621     %tmp = bitcast [59 x i64]* %pool to i8*
1622     call void @llvm.memmove.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1623     call void @llvm.memcpy.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1624     call void @llvm.memset.p0i8.i64(i8* nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
1625     %cmp3 = icmp eq i64 %n, 0
1626     %a = add i64 %x, %z
1627     %c = add i64 %x, %z
1628     ret i64 0
1629   })";
1630   LLVMContext Context;
1631   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1632 
1633   std::vector<IRInstructionData *> InstrList;
1634   std::vector<unsigned> UnsignedVec;
1635 
1636   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1637   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1638   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1639   Mapper.InstClassifier.EnableIntrinsics = true;
1640   getVectors(*M, Mapper, InstrList, UnsignedVec);
1641 
1642   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1643   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(9));
1644   ASSERT_LT(UnsignedVec[2], UnsignedVec[3]);
1645   ASSERT_LT(UnsignedVec[3], UnsignedVec[4]);
1646   ASSERT_LT(UnsignedVec[4], UnsignedVec[5]);
1647 }
1648 
1649 // Checks that a variable argument instructions are mapped to an illegal value.
1650 // We exclude variable argument instructions since variable arguments
1651 // requires extra checking of the argument list.
1652 TEST(IRInstructionMapper, VarArgsIllegal) {
1653   StringRef ModuleString = R"(
1654   declare void @llvm.va_start(i8*)
1655   declare void @llvm.va_copy(i8*, i8*)
1656   declare void @llvm.va_end(i8*)
1657 
1658   define i32 @func1(i32 %a, double %b, i8* %v, ...) nounwind {
1659   entry:
1660     %a.addr = alloca i32, align 4
1661     %b.addr = alloca double, align 8
1662     %ap = alloca i8*, align 4
1663     %c = alloca i32, align 4
1664     store i32 %a, i32* %a.addr, align 4
1665     store double %b, double* %b.addr, align 8
1666     %ap1 = bitcast i8** %ap to i8*
1667     call void @llvm.va_start(i8* %ap1)
1668     store double %b, double* %b.addr, align 8
1669     store double %b, double* %b.addr, align 8
1670     %0 = va_arg i8** %ap, i32
1671     store double %b, double* %b.addr, align 8
1672     store double %b, double* %b.addr, align 8
1673     call void @llvm.va_copy(i8* %v, i8* %ap1)
1674     store double %b, double* %b.addr, align 8
1675     store double %b, double* %b.addr, align 8
1676     call void @llvm.va_end(i8* %ap1)
1677     store i32 %0, i32* %c, align 4
1678     %tmp = load i32, i32* %c, align 4
1679     ret i32 %tmp
1680   })";
1681   LLVMContext Context;
1682   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1683 
1684   std::vector<IRInstructionData *> InstrList;
1685   std::vector<unsigned> UnsignedVec;
1686 
1687   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1688   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1689   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1690   Mapper.InstClassifier.EnableIntrinsics = false;
1691   getVectors(*M, Mapper, InstrList, UnsignedVec);
1692 
1693   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
1694   ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(17));
1695   ASSERT_TRUE(UnsignedVec[7] < UnsignedVec[0]);
1696   ASSERT_TRUE(UnsignedVec[13] < UnsignedVec[10]);
1697   ASSERT_TRUE(UnsignedVec[16] < UnsignedVec[13]);
1698 }
1699 
1700 // Check the length of adding two illegal instructions one after th other.  We
1701 // should find that only one element is added for each illegal range.
1702 TEST(IRInstructionMapper, RepeatedIllegalLength) {
1703   StringRef ModuleString = R"(
1704                           define i32 @f(i32 %a, i32 %b) {
1705                           bb0:
1706                              %0 = add i32 %a, %b
1707                              %1 = mul i32 %a, %b
1708                              %2 = alloca i32
1709                              %3 = alloca i32
1710                              %4 = add i32 %a, %b
1711                              %5 = mul i32 %a, %b
1712                              ret i32 0
1713                           })";
1714   LLVMContext Context;
1715   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1716 
1717   std::vector<IRInstructionData *> InstrList;
1718   std::vector<unsigned> UnsignedVec;
1719 
1720   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1721   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1722   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1723   getVectors(*M, Mapper, InstrList, UnsignedVec);
1724 
1725   // Check that the size of the unsigned vector and the instruction list are the
1726   // same as a safety check.
1727   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1728 
1729   // Make sure that the unsigned vector is the expected size.
1730   ASSERT_TRUE(UnsignedVec.size() == 6);
1731 }
1732 
1733 // A helper function that accepts an instruction list from a module made up of
1734 // two blocks of two legal instructions and terminator, and checks them for
1735 // instruction similarity.
1736 static bool longSimCandCompare(std::vector<IRInstructionData *> &InstrList,
1737                                bool Structure = false, unsigned Length = 2,
1738                                unsigned StartIdxOne = 0,
1739                                unsigned StartIdxTwo = 3) {
1740   std::vector<IRInstructionData *>::iterator Start, End;
1741 
1742   Start = InstrList.begin();
1743   End = InstrList.begin();
1744 
1745   std::advance(End, StartIdxOne + Length - 1);
1746   IRSimilarityCandidate Cand1(StartIdxOne, Length, *Start, *End);
1747 
1748   Start = InstrList.begin();
1749   End = InstrList.begin();
1750 
1751   std::advance(Start, StartIdxTwo);
1752   std::advance(End, StartIdxTwo + Length - 1);
1753   IRSimilarityCandidate Cand2(StartIdxTwo, Length, *Start, *End);
1754   if (Structure)
1755     return IRSimilarityCandidate::compareStructure(Cand1, Cand2);
1756   return IRSimilarityCandidate::isSimilar(Cand1, Cand2);
1757 }
1758 
1759 // Checks that two adds with commuted operands are considered to be the same
1760 // instructions.
1761 TEST(IRSimilarityCandidate, CheckIdenticalInstructions) {
1762   StringRef ModuleString = R"(
1763                           define i32 @f(i32 %a, i32 %b) {
1764                           bb0:
1765                              %0 = add i32 %a, %b
1766                              %1 = add i32 %b, %a
1767                              ret i32 0
1768                           })";
1769   LLVMContext Context;
1770   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1771 
1772   std::vector<IRInstructionData *> InstrList;
1773   std::vector<unsigned> UnsignedVec;
1774 
1775   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1776   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1777   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1778   getVectors(*M, Mapper, InstrList, UnsignedVec);
1779 
1780   // Check to make sure that we have a long enough region.
1781   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(3));
1782   // Check that the instructions were added correctly to both vectors.
1783   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1784 
1785   std::vector<IRInstructionData *>::iterator Start, End;
1786   Start = InstrList.begin();
1787   End = InstrList.begin();
1788   std::advance(End, 1);
1789   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
1790   IRSimilarityCandidate Cand2(0, 2, *Start, *End);
1791 
1792   ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1793 }
1794 
1795 // Checks that comparison instructions are found to be similar instructions
1796 // when the operands are flipped and the predicate is also swapped.
1797 TEST(IRSimilarityCandidate, PredicateIsomorphism) {
1798   StringRef ModuleString = R"(
1799                           define i32 @f(i32 %a, i32 %b) {
1800                           bb0:
1801                              %0 = icmp sgt i32 %a, %b
1802                              %1 = add i32 %b, %a
1803                              br label %bb1
1804                           bb1:
1805                              %2 = icmp slt i32 %a, %b
1806                              %3 = add i32 %a, %b
1807                              ret i32 0
1808                           })";
1809   LLVMContext Context;
1810   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1811 
1812   std::vector<IRInstructionData *> InstrList;
1813   std::vector<unsigned> UnsignedVec;
1814 
1815   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1816   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1817   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1818   getVectors(*M, Mapper, InstrList, UnsignedVec);
1819 
1820   ASSERT_TRUE(InstrList.size() > 5);
1821   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1822 
1823   std::vector<IRInstructionData *>::iterator Start, End;
1824   Start = InstrList.begin();
1825   End = InstrList.begin();
1826 
1827   std::advance(End, 1);
1828   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
1829 
1830   Start = InstrList.begin();
1831   End = InstrList.begin();
1832 
1833   std::advance(Start, 3);
1834   std::advance(End, 4);
1835   IRSimilarityCandidate Cand2(3, 2, *Start, *End);
1836 
1837   ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1838 }
1839 
1840 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1841 // are able to differentiate between instructions that have different opcodes.
1842 TEST(IRSimilarityCandidate, CheckRegionsDifferentInstruction) {
1843   StringRef ModuleString = R"(
1844                           define i32 @f(i32 %a, i32 %b) {
1845                           bb0:
1846                              %0 = add i32 %a, %b
1847                              %1 = add i32 %b, %a
1848                              ret i32 0
1849                           bb1:
1850                              %2 = sub i32 %a, %b
1851                              %3 = add i32 %b, %a
1852                              ret i32 0
1853                           })";
1854   LLVMContext Context;
1855   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1856 
1857   std::vector<IRInstructionData *> InstrList;
1858   std::vector<unsigned> UnsignedVec;
1859 
1860   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1861   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1862   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1863   getVectors(*M, Mapper, InstrList, UnsignedVec);
1864 
1865   // Check to make sure that we have a long enough region.
1866   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1867   // Check that the instructions were added correctly to both vectors.
1868   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1869 
1870   ASSERT_FALSE(longSimCandCompare(InstrList));
1871 }
1872 
1873 // Checks that IRSimilarityCandidates wrapping these two regions of instructions
1874 // are able to differentiate between instructions that have different types.
1875 TEST(IRSimilarityCandidate, CheckRegionsDifferentTypes) {
1876   StringRef ModuleString = R"(
1877                           define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
1878                           bb0:
1879                              %0 = add i32 %a, %b
1880                              %1 = add i32 %b, %a
1881                              ret i32 0
1882                           bb1:
1883                              %2 = add i64 %c, %d
1884                              %3 = add i64 %d, %c
1885                              ret i32 0
1886                           })";
1887   LLVMContext Context;
1888   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1889 
1890   std::vector<IRInstructionData *> InstrList;
1891   std::vector<unsigned> UnsignedVec;
1892 
1893   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1894   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1895   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1896   getVectors(*M, Mapper, InstrList, UnsignedVec);
1897 
1898   // Check to make sure that we have a long enough region.
1899   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1900   // Check that the instructions were added correctly to both vectors.
1901   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1902 
1903   ASSERT_FALSE(longSimCandCompare(InstrList));
1904 }
1905 
1906 // Check that debug instructions do not impact similarity. They are marked as
1907 // invisible.
1908 TEST(IRSimilarityCandidate, IdenticalWithDebug) {
1909   StringRef ModuleString = R"(
1910                           define i32 @f(i32 %a, i32 %b) {
1911                           bb0:
1912                              %0 = add i32 %a, %b
1913                              call void @llvm.dbg.value(metadata !0)
1914                              %1 = add i32 %b, %a
1915                              ret i32 0
1916                           bb1:
1917                              %2 = add i32 %a, %b
1918                              call void @llvm.dbg.value(metadata !1)
1919                              %3 = add i32 %b, %a
1920                              ret i32 0
1921                           bb2:
1922                              %4 = add i32 %a, %b
1923                              %5 = add i32 %b, %a
1924                              ret i32 0
1925                           }
1926 
1927                           declare void @llvm.dbg.value(metadata)
1928                           !0 = distinct !{!"test\00", i32 10}
1929                           !1 = distinct !{!"test\00", i32 11})";
1930   LLVMContext Context;
1931   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1932 
1933   std::vector<IRInstructionData *> InstrList;
1934   std::vector<unsigned> UnsignedVec;
1935 
1936   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1937   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1938   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1939   getVectors(*M, Mapper, InstrList, UnsignedVec);
1940 
1941   // Check to make sure that we have a long enough region.
1942   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(9));
1943   // Check that the instructions were added correctly to both vectors.
1944   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1945 
1946   ASSERT_TRUE(longSimCandCompare(InstrList));
1947 }
1948 
1949 // Checks that IRSimilarityCandidates that include illegal instructions, are not
1950 // considered to be the same set of instructions.  In these sets of instructions
1951 // the allocas are illegal.
1952 TEST(IRSimilarityCandidate, IllegalInCandidate) {
1953   StringRef ModuleString = R"(
1954                           define i32 @f(i32 %a, i32 %b) {
1955                           bb0:
1956                              %0 = add i32 %a, %b
1957                              %1 = add i32 %a, %b
1958                              %2 = alloca i32
1959                              ret i32 0
1960                           bb1:
1961                              %3 = add i32 %a, %b
1962                              %4 = add i32 %a, %b
1963                              %5 = alloca i32
1964                              ret i32 0
1965                           })";
1966   LLVMContext Context;
1967   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
1968 
1969   std::vector<IRInstructionData *> InstrList;
1970   std::vector<unsigned> UnsignedVec;
1971 
1972   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
1973   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
1974   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
1975   getVectors(*M, Mapper, InstrList, UnsignedVec);
1976 
1977   // Check to make sure that we have a long enough region.
1978   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
1979   // Check that the instructions were added correctly to both vectors.
1980   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
1981 
1982   std::vector<IRInstructionData *>::iterator Start, End;
1983 
1984   Start = InstrList.begin();
1985   End = InstrList.begin();
1986 
1987   std::advance(End, 2);
1988   IRSimilarityCandidate Cand1(0, 3, *Start, *End);
1989 
1990   Start = InstrList.begin();
1991   End = InstrList.begin();
1992 
1993   std::advance(Start, 3);
1994   std::advance(End, 5);
1995   IRSimilarityCandidate Cand2(3, 3, *Start, *End);
1996   ASSERT_FALSE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
1997 }
1998 
1999 // Checks that different structure, in this case, where we introduce a new
2000 // needed input in one region, is recognized as different.
2001 TEST(IRSimilarityCandidate, DifferentStructure) {
2002   StringRef ModuleString = R"(
2003                           define i32 @f(i32 %a, i32 %b) {
2004                           bb0:
2005                              %0 = add i32 %a, %b
2006                              %1 = add i32 %b, %a
2007                              ret i32 0
2008                           bb1:
2009                              %2 = add i32 %a, %b
2010                              %3 = add i32 %b, %0
2011                              ret i32 0
2012                           })";
2013   LLVMContext Context;
2014   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2015 
2016   std::vector<IRInstructionData *> InstrList;
2017   std::vector<unsigned> UnsignedVec;
2018 
2019   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2020   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2021   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2022   getVectors(*M, Mapper, InstrList, UnsignedVec);
2023 
2024   // Check to make sure that we have a long enough region.
2025   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2026   // Check that the instructions were added correctly to both vectors.
2027   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2028 
2029   ASSERT_FALSE(longSimCandCompare(InstrList, true));
2030 }
2031 
2032 // Checks that comparison instructions are found to have the same structure
2033 // when the operands are flipped and the predicate is also swapped.
2034 TEST(IRSimilarityCandidate, PredicateIsomorphismStructure) {
2035   StringRef ModuleString = R"(
2036                           define i32 @f(i32 %a, i32 %b) {
2037                           bb0:
2038                              %0 = icmp sgt i32 %a, %b
2039                              %1 = add i32 %a, %b
2040                              br label %bb1
2041                           bb1:
2042                              %2 = icmp slt i32 %b, %a
2043                              %3 = add i32 %a, %b
2044                              ret i32 0
2045                           })";
2046   LLVMContext Context;
2047   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2048 
2049   std::vector<IRInstructionData *> InstrList;
2050   std::vector<unsigned> UnsignedVec;
2051 
2052   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2053   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2054   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2055   getVectors(*M, Mapper, InstrList, UnsignedVec);
2056 
2057   ASSERT_TRUE(InstrList.size() > 5);
2058   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2059 
2060   ASSERT_TRUE(longSimCandCompare(InstrList, true));
2061 }
2062 
2063 // Checks that different predicates are counted as diferent.
2064 TEST(IRSimilarityCandidate, PredicateDifference) {
2065   StringRef ModuleString = R"(
2066                           define i32 @f(i32 %a, i32 %b) {
2067                           bb0:
2068                              %0 = icmp sge i32 %a, %b
2069                              %1 = add i32 %b, %a
2070                              br label %bb1
2071                           bb1:
2072                              %2 = icmp slt i32 %b, %a
2073                              %3 = add i32 %a, %b
2074                              ret i32 0
2075                           })";
2076   LLVMContext Context;
2077   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2078 
2079   std::vector<IRInstructionData *> InstrList;
2080   std::vector<unsigned> UnsignedVec;
2081 
2082   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2083   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2084   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2085   getVectors(*M, Mapper, InstrList, UnsignedVec);
2086 
2087   ASSERT_TRUE(InstrList.size() > 5);
2088   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2089 
2090   ASSERT_FALSE(longSimCandCompare(InstrList));
2091 }
2092 
2093 // Checks that the same structure is recognized between two candidates. The
2094 // items %a and %b are used in the same way in both sets of instructions.
2095 TEST(IRSimilarityCandidate, SameStructure) {
2096   StringRef ModuleString = R"(
2097                           define i32 @f(i32 %a, i32 %b) {
2098                           bb0:
2099                              %0 = add i32 %a, %b
2100                              %1 = sub i32 %b, %a
2101                              ret i32 0
2102                           bb1:
2103                              %2 = add i32 %a, %b
2104                              %3 = sub i32 %b, %a
2105                              ret i32 0
2106                           })";
2107   LLVMContext Context;
2108   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2109 
2110   std::vector<IRInstructionData *> InstrList;
2111   std::vector<unsigned> UnsignedVec;
2112 
2113   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2114   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2115   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2116   getVectors(*M, Mapper, InstrList, UnsignedVec);
2117 
2118   // Check to make sure that we have a long enough region.
2119   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2120   // Check that the instructions were added correctly to both vectors.
2121   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2122 
2123   ASSERT_TRUE(longSimCandCompare(InstrList, true));
2124 }
2125 
2126 // Checks that the canonical numbering between two candidates matches the found
2127 // mapping between two candidates.
2128 TEST(IRSimilarityCandidate, CanonicalNumbering) {
2129   StringRef ModuleString = R"(
2130                           define i32 @f(i32 %a, i32 %b) {
2131                           bb0:
2132                              %0 = add i32 %a, %b
2133                              %1 = sub i32 %b, %a
2134                              ret i32 0
2135                           bb1:
2136                              %2 = add i32 %a, %b
2137                              %3 = sub i32 %b, %a
2138                              ret i32 0
2139                           })";
2140   LLVMContext Context;
2141   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2142 
2143   std::vector<IRInstructionData *> InstrList;
2144   std::vector<unsigned> UnsignedVec;
2145 
2146   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2147   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2148   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2149   getVectors(*M, Mapper, InstrList, UnsignedVec);
2150 
2151   // Check to make sure that we have a long enough region.
2152   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2153   // Check that the instructions were added correctly to both vectors.
2154   ASSERT_EQ(InstrList.size(), UnsignedVec.size());
2155 
2156   std::vector<IRInstructionData *>::iterator Start, End;
2157 
2158   Start = InstrList.begin();
2159   End = InstrList.begin();
2160 
2161   std::advance(End, 1);
2162   IRSimilarityCandidate Cand1(0, 2, *Start, *End);
2163 
2164   Start = InstrList.begin();
2165   End = InstrList.begin();
2166 
2167   std::advance(Start, 3);
2168   std::advance(End, 4);
2169   IRSimilarityCandidate Cand2(3, 2, *Start, *End);
2170   DenseMap<unsigned, DenseSet<unsigned>> Mapping1;
2171   DenseMap<unsigned, DenseSet<unsigned>> Mapping2;
2172   ASSERT_TRUE(IRSimilarityCandidate::compareStructure(Cand1, Cand2, Mapping1,
2173                                                       Mapping2));
2174   IRSimilarityCandidate::createCanonicalMappingFor(Cand1);
2175   Cand2.createCanonicalRelationFrom(Cand1, Mapping1, Mapping2);
2176 
2177   for (std::pair<unsigned, DenseSet<unsigned>> &P : Mapping2) {
2178     unsigned Source = P.first;
2179 
2180     ASSERT_TRUE(Cand2.getCanonicalNum(Source).hasValue());
2181     unsigned Canon = *Cand2.getCanonicalNum(Source);
2182     ASSERT_TRUE(Cand1.fromCanonicalNum(Canon).hasValue());
2183     unsigned Dest = *Cand1.fromCanonicalNum(Canon);
2184 
2185     DenseSet<unsigned>::iterator It = P.second.find(Dest);
2186     ASSERT_NE(It, P.second.end());
2187   }
2188 }
2189 
2190 // Checks that the same structure is recognized between two candidates. While
2191 // the input names are reversed, they still perform the same overall operation.
2192 TEST(IRSimilarityCandidate, DifferentNameSameStructure) {
2193   StringRef ModuleString = R"(
2194                           define i32 @f(i32 %a, i32 %b) {
2195                           bb0:
2196                              %0 = add i32 %a, %b
2197                              %1 = add i32 %b, %a
2198                              ret i32 0
2199                           bb1:
2200                              %2 = add i32 %b, %a
2201                              %3 = add i32 %a, %b
2202                              ret i32 0
2203                           })";
2204   LLVMContext Context;
2205   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2206 
2207   std::vector<IRInstructionData *> InstrList;
2208   std::vector<unsigned> UnsignedVec;
2209 
2210   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2211   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2212   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2213   getVectors(*M, Mapper, InstrList, UnsignedVec);
2214 
2215   // Check to make sure that we have a long enough region.
2216   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
2217   // Check that the instructions were added correctly to both vectors.
2218   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2219 
2220   ASSERT_TRUE(longSimCandCompare(InstrList, true));
2221 }
2222 
2223 // Checks that the same structure is recognized between two candidates when
2224 // the branches target other blocks inside the same region, the relative
2225 // distance between the blocks must be the same.
2226 TEST(IRSimilarityCandidate, SameBranchStructureInternal) {
2227   StringRef ModuleString = R"(
2228                           define i32 @f(i32 %a, i32 %b) {
2229                           bb0:
2230                              %0 = add i32 %a, %b
2231                              %1 = add i32 %b, %a
2232                              br label %bb1
2233                           bb1:
2234                              %2 = add i32 %b, %a
2235                              %3 = add i32 %a, %b
2236                              ret i32 0
2237                           }
2238 
2239                           define i32 @f2(i32 %a, i32 %b) {
2240                           bb0:
2241                              %0 = add i32 %a, %b
2242                              %1 = add i32 %b, %a
2243                              br label %bb1
2244                           bb1:
2245                              %2 = add i32 %b, %a
2246                              %3 = add i32 %a, %b
2247                              ret i32 0
2248                           })";
2249   LLVMContext Context;
2250   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2251 
2252   std::vector<IRInstructionData *> InstrList;
2253   std::vector<unsigned> UnsignedVec;
2254 
2255   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2256   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2257   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2258   Mapper.InstClassifier.EnableBranches = true;
2259   Mapper.initializeForBBs(*M);
2260   getVectors(*M, Mapper, InstrList, UnsignedVec);
2261 
2262   // Check to make sure that we have a long enough region.
2263   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(12));
2264   // Check that the instructions were added correctly to both vectors.
2265   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2266 
2267   ASSERT_TRUE(longSimCandCompare(InstrList, true, 5, 0, 6));
2268 }
2269 
2270 // Checks that the different structure is recognized between two candidates,
2271 // when the branches target other blocks inside the same region, the relative
2272 // distance between the blocks must be the same.
2273 TEST(IRSimilarityCandidate, DifferentBranchStructureInternal) {
2274   StringRef ModuleString = R"(
2275                           define i32 @f(i32 %a, i32 %b) {
2276                           bb0:
2277                              %0 = add i32 %a, %b
2278                              %1 = add i32 %b, %a
2279                              br label %bb2
2280                           bb1:
2281                              %2 = add i32 %b, %a
2282                              %3 = add i32 %a, %b
2283                              br label %bb2
2284                           bb2:
2285                              %4 = add i32 %b, %a
2286                              %5 = add i32 %a, %b
2287                              ret i32 0
2288                           }
2289 
2290                           define i32 @f2(i32 %a, i32 %b) {
2291                           bb0:
2292                              %0 = add i32 %a, %b
2293                              %1 = add i32 %b, %a
2294                              br label %bb1
2295                           bb1:
2296                              %2 = add i32 %b, %a
2297                              %3 = add i32 %a, %b
2298                              br label %bb2
2299                           bb2:
2300                              %4 = add i32 %b, %a
2301                              %5 = add i32 %a, %b
2302                              ret i32 0
2303                           })";
2304   LLVMContext Context;
2305   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2306 
2307   std::vector<IRInstructionData *> InstrList;
2308   std::vector<unsigned> UnsignedVec;
2309 
2310   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2311   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2312   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2313   Mapper.InstClassifier.EnableBranches = true;
2314   Mapper.initializeForBBs(*M);
2315   getVectors(*M, Mapper, InstrList, UnsignedVec);
2316 
2317   // Check to make sure that we have a long enough region.
2318   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(18));
2319   // Check that the instructions were added correctly to both vectors.
2320   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2321 
2322   ASSERT_FALSE(longSimCandCompare(InstrList, true, 6, 0, 9));
2323 }
2324 
2325 // Checks that the same structure is recognized between two candidates, when
2326 // the branches target other blocks outside region, the relative distance
2327 // does not need to be the same.
2328 TEST(IRSimilarityCandidate, SameBranchStructureOutside) {
2329   StringRef ModuleString = R"(
2330                           define i32 @f(i32 %a, i32 %b) {
2331                           bb0:
2332                              %0 = add i32 %a, %b
2333                              %1 = add i32 %b, %a
2334                              br label %bb1
2335                           bb1:
2336                              %2 = add i32 %b, %a
2337                              %3 = add i32 %a, %b
2338                              ret i32 0
2339                           }
2340 
2341                           define i32 @f2(i32 %a, i32 %b) {
2342                           bb0:
2343                              %0 = add i32 %a, %b
2344                              %1 = add i32 %b, %a
2345                              br label %bb1
2346                           bb1:
2347                              %2 = add i32 %b, %a
2348                              %3 = add i32 %a, %b
2349                              ret i32 0
2350                           })";
2351   LLVMContext Context;
2352   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2353 
2354   std::vector<IRInstructionData *> InstrList;
2355   std::vector<unsigned> UnsignedVec;
2356 
2357   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2358   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2359   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2360   Mapper.InstClassifier.EnableBranches = true;
2361   Mapper.initializeForBBs(*M);
2362   getVectors(*M, Mapper, InstrList, UnsignedVec);
2363 
2364   // Check to make sure that we have a long enough region.
2365   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(12));
2366   // Check that the instructions were added correctly to both vectors.
2367   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2368 
2369   ASSERT_TRUE(longSimCandCompare(InstrList, true, 3, 0, 6));
2370 }
2371 
2372 // Checks that the same structure is recognized between two candidates, when
2373 // the branches target other blocks outside region, the relative distance
2374 // does not need to be the same.
2375 TEST(IRSimilarityCandidate, DifferentBranchStructureOutside) {
2376   StringRef ModuleString = R"(
2377                           define i32 @f(i32 %a, i32 %b) {
2378                           bb0:
2379                              %0 = add i32 %a, %b
2380                              %1 = add i32 %b, %a
2381                              br label %bb1
2382                           bb1:
2383                              %2 = add i32 %b, %a
2384                              %3 = add i32 %a, %b
2385                              ret i32 0
2386                           }
2387 
2388                           define i32 @f2(i32 %a, i32 %b) {
2389                           bb0:
2390                              %0 = add i32 %a, %b
2391                              %1 = add i32 %b, %a
2392                              br label %bb2
2393                           bb1:
2394                              %2 = add i32 %b, %a
2395                              %3 = add i32 %a, %b
2396                              br label %bb2
2397                           bb2:
2398                              %4 = add i32 %b, %a
2399                              %5 = add i32 %a, %b
2400                              ret i32 0
2401                           })";
2402   LLVMContext Context;
2403   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2404 
2405   std::vector<IRInstructionData *> InstrList;
2406   std::vector<unsigned> UnsignedVec;
2407 
2408   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2409   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2410   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2411   Mapper.InstClassifier.EnableBranches = true;
2412   Mapper.initializeForBBs(*M);
2413   getVectors(*M, Mapper, InstrList, UnsignedVec);
2414 
2415   // Check to make sure that we have a long enough region.
2416   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(15));
2417   // Check that the instructions were added correctly to both vectors.
2418   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2419 
2420   ASSERT_TRUE(longSimCandCompare(InstrList, true, 3, 0, 6));
2421 }
2422 
2423 // Checks that the same structure is recognized between two candidates,
2424 // when the phi predecessor are other blocks inside the same region,
2425 // the relative distance between the blocks must be the same.
2426 TEST(IRSimilarityCandidate, SamePHIStructureInternal) {
2427   StringRef ModuleString = R"(
2428                           define i32 @f(i32 %a, i32 %b) {
2429                           bb0:
2430                              br label %bb2
2431                           bb1:
2432                              br label %bb2
2433                           bb2:
2434                              %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2435                              %1 = add i32 %b, %a
2436                              %2 = add i32 %a, %b
2437                              ret i32 0
2438                           }
2439 
2440                           define i32 @f2(i32 %a, i32 %b) {
2441                           bb0:
2442                              br label %bb2
2443                           bb1:
2444                              br label %bb2
2445                           bb2:
2446                              %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2447                              %1 = add i32 %b, %a
2448                              %2 = add i32 %a, %b
2449                              ret i32 0
2450                           })";
2451   LLVMContext Context;
2452   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2453 
2454   std::vector<IRInstructionData *> InstrList;
2455   std::vector<unsigned> UnsignedVec;
2456 
2457   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2458   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2459   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2460   Mapper.InstClassifier.EnableBranches = true;
2461   Mapper.initializeForBBs(*M);
2462   getVectors(*M, Mapper, InstrList, UnsignedVec);
2463 
2464   // Check to make sure that we have a long enough region.
2465   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(11));
2466   // Check that the instructions were added correctly to both vectors.
2467   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2468 
2469   ASSERT_TRUE(longSimCandCompare(InstrList, true, 4, 0, 6));
2470 }
2471 
2472 // Checks that the different structure is recognized between two candidates,
2473 // when the phi predecessor are other blocks inside the same region,
2474 // the relative distance between the blocks must be the same.
2475 TEST(IRSimilarityCandidate, DifferentPHIStructureInternal) {
2476   StringRef ModuleString = R"(
2477                           define i32 @f(i32 %a, i32 %b) {
2478                           bb0:
2479                              br label %bb2
2480                           bb1:
2481                              br label %bb2
2482                           bb3:
2483                              br label %bb2
2484                           bb2:
2485                              %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
2486                              %1 = add i32 %b, %a
2487                              %2 = add i32 %a, %b
2488                              ret i32 0
2489                           }
2490 
2491                           define i32 @f2(i32 %a, i32 %b) {
2492                           bb0:
2493                              br label %bb2
2494                           bb1:
2495                              br label %bb2
2496                           bb3:
2497                              br label %bb2
2498                           bb2:
2499                              %0 = phi i32 [ %a, %bb0 ], [ %b, %bb3 ]
2500                              %1 = add i32 %b, %a
2501                              %2 = add i32 %a, %b
2502                              ret i32 0
2503                           })";
2504   LLVMContext Context;
2505   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2506 
2507   std::vector<IRInstructionData *> InstrList;
2508   std::vector<unsigned> UnsignedVec;
2509 
2510   SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
2511   SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
2512   IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
2513   Mapper.InstClassifier.EnableBranches = true;
2514   Mapper.initializeForBBs(*M);
2515   getVectors(*M, Mapper, InstrList, UnsignedVec);
2516 
2517   // Check to make sure that we have a long enough region.
2518   ASSERT_EQ(InstrList.size(), static_cast<unsigned>(13));
2519   // Check that the instructions were added correctly to both vectors.
2520   ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
2521 
2522   ASSERT_FALSE(longSimCandCompare(InstrList, true, 5, 0, 7));
2523 }
2524 
2525 // Checks that two sets of identical instructions are found to be the same.
2526 // Both sequences of adds have the same operand ordering, and the same
2527 // instructions, making them strcturally equivalent.
2528 TEST(IRSimilarityIdentifier, IdentitySimilarity) {
2529   StringRef ModuleString = R"(
2530                           define i32 @f(i32 %a, i32 %b) {
2531                           bb0:
2532                              %0 = add i32 %a, %b
2533                              %1 = sub i32 %b, %a
2534                              br label %bb1
2535                           bb1:
2536                              %2 = add i32 %a, %b
2537                              %3 = sub i32 %b, %a
2538                              ret i32 0
2539                           })";
2540   LLVMContext Context;
2541   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2542 
2543   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2544   getSimilarities(*M, SimilarityCandidates);
2545 
2546   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2547   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2548     ASSERT_TRUE(Cands.size() == 2);
2549     unsigned InstIdx = 0;
2550     for (IRSimilarityCandidate &Cand : Cands) {
2551       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2552       InstIdx += 3;
2553     }
2554   }
2555 }
2556 
2557 // Checks that incorrect sequences are not found as similar.  In this case,
2558 // we have different sequences of instructions.
2559 TEST(IRSimilarityIdentifier, InstructionDifference) {
2560   StringRef ModuleString = R"(
2561                           define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2562                           bb0:
2563                              %0 = sub i32 %a, %b
2564                              %1 = add i32 %b, %a
2565                              br label %bb1
2566                           bb1:
2567                              %2 = add i32 %c, %d
2568                              %3 = sub i32 %d, %c
2569                              ret i32 0
2570                           })";
2571   LLVMContext Context;
2572   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2573 
2574   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2575   getSimilarities(*M, SimilarityCandidates);
2576 
2577   ASSERT_TRUE(SimilarityCandidates.empty());
2578 }
2579 
2580 // This test checks to see whether we can detect similarity for commutative
2581 // instructions where the operands have been reversed.
2582 TEST(IRSimilarityIdentifier, CommutativeSimilarity) {
2583   StringRef ModuleString = R"(
2584                           define i32 @f(i32 %a, i32 %b) {
2585                           bb0:
2586                              %0 = add i32 %a, %b
2587                              %1 = add i32 %b, %a
2588                              br label %bb1
2589                           bb1:
2590                              %2 = add i32 %a, %b
2591                              %3 = add i32 %a, %b
2592                              ret i32 0
2593                           })";
2594   LLVMContext Context;
2595   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2596 
2597   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2598   getSimilarities(*M, SimilarityCandidates);
2599 
2600   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2601   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2602     ASSERT_TRUE(Cands.size() == 2);
2603     unsigned InstIdx = 0;
2604     for (IRSimilarityCandidate &Cand : Cands) {
2605       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2606       InstIdx += 3;
2607     }
2608   }
2609 }
2610 
2611 // This test checks to see whether we can detect different structure in
2612 // commutative instructions.  In this case, the second operand in the second
2613 // add is different.
2614 TEST(IRSimilarityIdentifier, NoCommutativeSimilarity) {
2615   StringRef ModuleString = R"(
2616                           define i32 @f(i32 %a, i32 %b) {
2617                           bb0:
2618                              %0 = add i32 %a, %b
2619                              %1 = add i32 %1, %b
2620                              br label %bb1
2621                           bb1:
2622                              %2 = add i32 %a, %b
2623                              %3 = add i32 %2, %a
2624                              ret i32 0
2625                           })";
2626   LLVMContext Context;
2627   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2628 
2629   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2630   getSimilarities(*M, SimilarityCandidates);
2631 
2632   ASSERT_TRUE(SimilarityCandidates.size() == 0);
2633 }
2634 
2635 // Check that we are not finding similarity in non commutative
2636 // instructions.  That is, while the instruction and operands used are the same
2637 // in the two subtraction sequences, they are in a different order, and cannot
2638 // be counted as the same since a subtraction is not commutative.
2639 TEST(IRSimilarityIdentifier, NonCommutativeDifference) {
2640   StringRef ModuleString = R"(
2641                           define i32 @f(i32 %a, i32 %b) {
2642                           bb0:
2643                              %0 = sub i32 %a, %b
2644                              %1 = sub i32 %b, %a
2645                              br label %bb1
2646                           bb1:
2647                              %2 = sub i32 %a, %b
2648                              %3 = sub i32 %a, %b
2649                              ret i32 0
2650                           })";
2651   LLVMContext Context;
2652   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2653 
2654   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2655   getSimilarities(*M, SimilarityCandidates);
2656 
2657   ASSERT_TRUE(SimilarityCandidates.empty());
2658 }
2659 
2660 // Check that we find similarity despite changing the register names.
2661 TEST(IRSimilarityIdentifier, MappingSimilarity) {
2662   StringRef ModuleString = R"(
2663                           define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
2664                           bb0:
2665                              %0 = add i32 %a, %b
2666                              %1 = sub i32 %b, %a
2667                              br label %bb1
2668                           bb1:
2669                              %2 = add i32 %c, %d
2670                              %3 = sub i32 %d, %c
2671                              ret i32 0
2672                           })";
2673   LLVMContext Context;
2674   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2675 
2676   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2677   getSimilarities(*M, SimilarityCandidates);
2678 
2679   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2680   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2681     ASSERT_TRUE(Cands.size() == 2);
2682     unsigned InstIdx = 0;
2683     for (IRSimilarityCandidate &Cand : Cands) {
2684       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2685       InstIdx += 3;
2686     }
2687   }
2688 }
2689 
2690 // Check that we find instances of swapped predicate isomorphism.  That is,
2691 // for predicates that can be flipped, e.g. greater than to less than,
2692 // we can identify that instances of these different literal predicates, but are
2693 // the same within a single swap can be found.
2694 TEST(IRSimilarityIdentifier, PredicateIsomorphism) {
2695   StringRef ModuleString = R"(
2696                           define i32 @f(i32 %a, i32 %b) {
2697                           bb0:
2698                              %0 = add i32 %a, %b
2699                              %1 = icmp sgt i32 %b, %a
2700                              br label %bb1
2701                           bb1:
2702                              %2 = add i32 %a, %b
2703                              %3 = icmp slt i32 %a, %b
2704                              ret i32 0
2705                           })";
2706   LLVMContext Context;
2707   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2708 
2709   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2710   getSimilarities(*M, SimilarityCandidates);
2711 
2712   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2713   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2714     ASSERT_TRUE(Cands.size() == 2);
2715     unsigned InstIdx = 0;
2716     for (IRSimilarityCandidate &Cand : Cands) {
2717       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2718       InstIdx += 3;
2719     }
2720   }
2721 }
2722 
2723 // Checks that constants are detected as the same operand in each use in the
2724 // sequences of instructions.  Also checks that we can find structural
2725 // equivalence using constants.  In this case the 1 has the same use pattern as
2726 // %a.
2727 TEST(IRSimilarityIdentifier, ConstantMappingSimilarity) {
2728   StringRef ModuleString = R"(
2729                           define i32 @f(i32 %a, i32 %b) {
2730                           bb0:
2731                              %0 = add i32 1, %b
2732                              %1 = icmp sgt i32 %b, 1
2733                              br label %bb1
2734                           bb1:
2735                              %2 = add i32 %a, %b
2736                              %3 = icmp sgt i32 %b, %a
2737                              ret i32 0
2738                           })";
2739   LLVMContext Context;
2740   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2741 
2742   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2743   getSimilarities(*M, SimilarityCandidates);
2744 
2745   ASSERT_TRUE(SimilarityCandidates.size() == 1);
2746   for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
2747     ASSERT_TRUE(Cands.size() == 2);
2748     unsigned InstIdx = 0;
2749     for (IRSimilarityCandidate &Cand : Cands) {
2750       ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
2751       InstIdx += 3;
2752     }
2753   }
2754 }
2755 
2756 // Check that constants are uniquely identified. i.e. two different constants
2757 // are not considered the same.  This means that this should not find any
2758 // structural similarity.
2759 TEST(IRSimilarityIdentifier, ConstantMappingDifference) {
2760   StringRef ModuleString = R"(
2761                           define i32 @f(i32 %a, i32 %b) {
2762                           bb0:
2763                              %0 = add i32 1, %b
2764                              %1 = icmp sgt i32 %b, 2
2765                              br label %bb1
2766                           bb1:
2767                              %2 = add i32 %a, %b
2768                              %3 = icmp slt i32 %a, %b
2769                              ret i32 0
2770                           })";
2771   LLVMContext Context;
2772   std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
2773 
2774   std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
2775   getSimilarities(*M, SimilarityCandidates);
2776 
2777   ASSERT_TRUE(SimilarityCandidates.empty());
2778 }
2779