xref: /llvm-project/llvm/unittests/IR/StructuralHashTest.cpp (revision 0dd9fdcf83cd00f51669b32c96937a97ef4b339e)
1bdbb3fd5SArthur Eubanks //===- llvm/unittest/IR/StructuralHashTest.cpp ----------------------------===//
2bdbb3fd5SArthur Eubanks //
3bdbb3fd5SArthur Eubanks // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdbb3fd5SArthur Eubanks // See https://llvm.org/LICENSE.txt for license information.
5bdbb3fd5SArthur Eubanks // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdbb3fd5SArthur Eubanks //
7bdbb3fd5SArthur Eubanks //===----------------------------------------------------------------------===//
8bdbb3fd5SArthur Eubanks 
9bdbb3fd5SArthur Eubanks #include "llvm/IR/StructuralHash.h"
10bdbb3fd5SArthur Eubanks #include "llvm/AsmParser/Parser.h"
11bdbb3fd5SArthur Eubanks #include "llvm/IR/Module.h"
12bdbb3fd5SArthur Eubanks #include "llvm/Support/SourceMgr.h"
13*0dd9fdcfSKyungwoo Lee #include "gmock/gmock-matchers.h"
14bdbb3fd5SArthur Eubanks #include "gtest/gtest.h"
15bdbb3fd5SArthur Eubanks 
16e8e499f5SPaul Kirth #include <memory>
17e8e499f5SPaul Kirth 
18bdbb3fd5SArthur Eubanks using namespace llvm;
19bdbb3fd5SArthur Eubanks 
20bdbb3fd5SArthur Eubanks namespace {
21bdbb3fd5SArthur Eubanks 
22*0dd9fdcfSKyungwoo Lee using testing::Contains;
23*0dd9fdcfSKyungwoo Lee using testing::Key;
24*0dd9fdcfSKyungwoo Lee using testing::Pair;
25*0dd9fdcfSKyungwoo Lee using testing::SizeIs;
26*0dd9fdcfSKyungwoo Lee 
27bdbb3fd5SArthur Eubanks std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
28bdbb3fd5SArthur Eubanks   SMDiagnostic Err;
29bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Context);
30bdbb3fd5SArthur Eubanks   if (!M)
31bdbb3fd5SArthur Eubanks     Err.print("StructuralHashTest", errs());
32bdbb3fd5SArthur Eubanks   return M;
33bdbb3fd5SArthur Eubanks }
34bdbb3fd5SArthur Eubanks 
35bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, Empty) {
36bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
37bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "");
38bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "");
39bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
40bdbb3fd5SArthur Eubanks }
41bdbb3fd5SArthur Eubanks 
42bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, Basic) {
43bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
44bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M0 = parseIR(Ctx, "");
45bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }");
46bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f() { ret void }");
47bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M3 = parseIR(Ctx, "@g = global i32 2");
48bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M4 = parseIR(Ctx, "@g = global i32 2");
49bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M0), StructuralHash(*M1));
50bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M0), StructuralHash(*M3));
51bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M1), StructuralHash(*M3));
52bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
53bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M3), StructuralHash(*M4));
54bdbb3fd5SArthur Eubanks }
55bdbb3fd5SArthur Eubanks 
56bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, BasicFunction) {
57bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
58bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M = parseIR(Ctx, "define void @f() {\n"
59bdbb3fd5SArthur Eubanks                                            "  ret void\n"
60bdbb3fd5SArthur Eubanks                                            "}\n"
61bdbb3fd5SArthur Eubanks                                            "define void @g() {\n"
62bdbb3fd5SArthur Eubanks                                            "  ret void\n"
63bdbb3fd5SArthur Eubanks                                            "}\n"
64bdbb3fd5SArthur Eubanks                                            "define i32 @h(i32 %i) {\n"
65bdbb3fd5SArthur Eubanks                                            "  ret i32 %i\n"
66bdbb3fd5SArthur Eubanks                                            "}\n");
67bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M->getFunction("f")),
68bdbb3fd5SArthur Eubanks             StructuralHash(*M->getFunction("g")));
69bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M->getFunction("f")),
70bdbb3fd5SArthur Eubanks             StructuralHash(*M->getFunction("h")));
71bdbb3fd5SArthur Eubanks }
72bdbb3fd5SArthur Eubanks 
73bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, Declaration) {
74bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
75bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M0 = parseIR(Ctx, "");
76bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "declare void @f()");
77bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "@g = external global i32");
78bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M1));
79bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M2));
80bdbb3fd5SArthur Eubanks }
81bdbb3fd5SArthur Eubanks 
82bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, GlobalType) {
83bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
84bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "@g = global i32 1");
85bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "@g = global float 1.0");
86bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2));
87bdbb3fd5SArthur Eubanks }
88bdbb3fd5SArthur Eubanks 
89bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, Function) {
90bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
91bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }");
92bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f(i32) { ret void }");
93bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2));
94bdbb3fd5SArthur Eubanks }
95bdbb3fd5SArthur Eubanks 
96bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, FunctionRetType) {
97bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
98bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }");
99bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i32 @f() { ret i32 0 }");
100bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
101f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
102bdbb3fd5SArthur Eubanks }
103bdbb3fd5SArthur Eubanks 
104bdbb3fd5SArthur Eubanks TEST(StructuralHashTest, InstructionOpCode) {
105bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
106bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f(ptr %p) {\n"
107bdbb3fd5SArthur Eubanks                                             "  %a = load i32, ptr %p\n"
108bdbb3fd5SArthur Eubanks                                             "  ret void\n"
109bdbb3fd5SArthur Eubanks                                             "}\n");
110bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 =
111bdbb3fd5SArthur Eubanks       parseIR(Ctx, "define void @f(ptr %p) {\n"
112bdbb3fd5SArthur Eubanks                    "  %a = getelementptr i8, ptr %p, i32 1\n"
113bdbb3fd5SArthur Eubanks                    "  ret void\n"
114bdbb3fd5SArthur Eubanks                    "}\n");
115bdbb3fd5SArthur Eubanks   EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2));
116bdbb3fd5SArthur Eubanks }
117bdbb3fd5SArthur Eubanks 
118f532d61dSAiden Grossman TEST(StructuralHashTest, InstructionSubType) {
119bdbb3fd5SArthur Eubanks   LLVMContext Ctx;
120bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f(ptr %p) {\n"
121bdbb3fd5SArthur Eubanks                                             "  %a = load i32, ptr %p\n"
122bdbb3fd5SArthur Eubanks                                             "  ret void\n"
123bdbb3fd5SArthur Eubanks                                             "}\n");
124bdbb3fd5SArthur Eubanks   std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f(ptr %p) {\n"
125bdbb3fd5SArthur Eubanks                                             "  %a = load i64, ptr %p\n"
126bdbb3fd5SArthur Eubanks                                             "  ret void\n"
127bdbb3fd5SArthur Eubanks                                             "}\n");
128bdbb3fd5SArthur Eubanks   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
129f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
130f532d61dSAiden Grossman }
131f532d61dSAiden Grossman 
132f532d61dSAiden Grossman TEST(StructuralHashTest, InstructionType) {
133f532d61dSAiden Grossman   LLVMContext Ctx;
134f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f(ptr %p) {\n"
135f532d61dSAiden Grossman                                             "  %1 = load i32, ptr %p\n"
136f532d61dSAiden Grossman                                             "  ret void\n"
137f532d61dSAiden Grossman                                             "}\n");
138f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f(ptr %p) {\n"
139f532d61dSAiden Grossman                                             "  %1 = load float, ptr %p\n"
140f532d61dSAiden Grossman                                             "  ret void\n"
141f532d61dSAiden Grossman                                             "}\n");
142f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
143f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
144bdbb3fd5SArthur Eubanks }
145bdbb3fd5SArthur Eubanks 
146e8e499f5SPaul Kirth TEST(StructuralHashTest, IgnoredMetadata) {
147e8e499f5SPaul Kirth   LLVMContext Ctx;
148e8e499f5SPaul Kirth   std::unique_ptr<Module> M1 = parseIR(Ctx, "@a = global i32 1\n");
149e8e499f5SPaul Kirth   // clang-format off
150e8e499f5SPaul Kirth   std::unique_ptr<Module> M2 = parseIR(
151e8e499f5SPaul Kirth       Ctx, R"(
152e8e499f5SPaul Kirth         @a = global i32 1
153e8e499f5SPaul Kirth         @llvm.embedded.object = private constant [4 x i8] c"BC\C0\00", section ".llvm.lto", align 1, !exclude !0
154e8e499f5SPaul Kirth         @llvm.compiler.used = appending global [1 x ptr] [ptr @llvm.embedded.object], section "llvm.metadata"
155e8e499f5SPaul Kirth 
156e8e499f5SPaul Kirth         !llvm.embedded.objects = !{!1}
157e8e499f5SPaul Kirth 
158e8e499f5SPaul Kirth         !0 = !{}
159e8e499f5SPaul Kirth         !1 = !{ptr @llvm.embedded.object, !".llvm.lto"}
160e8e499f5SPaul Kirth         )");
161f532d61dSAiden Grossman   // clang-format on
162e8e499f5SPaul Kirth   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
163e8e499f5SPaul Kirth }
164f532d61dSAiden Grossman 
165f532d61dSAiden Grossman TEST(StructuralHashTest, ComparisonInstructionPredicate) {
166f532d61dSAiden Grossman   LLVMContext Ctx;
167f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i1 @f(i64 %a, i64 %b) {\n"
168f532d61dSAiden Grossman                                             "  %1 = icmp eq i64 %a, %b\n"
169f532d61dSAiden Grossman                                             "  ret i1 %1\n"
170f532d61dSAiden Grossman                                             "}\n");
171f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i1 @f(i64 %a, i64 %b) {\n"
172f532d61dSAiden Grossman                                             "  %1 = icmp ne i64 %a, %b\n"
173f532d61dSAiden Grossman                                             " ret i1 %1\n"
174f532d61dSAiden Grossman                                             "}\n");
175f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
176f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
177f532d61dSAiden Grossman }
178f532d61dSAiden Grossman 
179f532d61dSAiden Grossman TEST(StructuralHashTest, IntrinsicInstruction) {
180f532d61dSAiden Grossman   LLVMContext Ctx;
181f532d61dSAiden Grossman   std::unique_ptr<Module> M1 =
182f532d61dSAiden Grossman       parseIR(Ctx, "define float @f(float %a) {\n"
183f532d61dSAiden Grossman                    "  %b = call float @llvm.sin.f32(float %a)\n"
184f532d61dSAiden Grossman                    "  ret float %b\n"
185f532d61dSAiden Grossman                    "}\n"
186f532d61dSAiden Grossman                    "declare float @llvm.sin.f32(float)\n");
187f532d61dSAiden Grossman   std::unique_ptr<Module> M2 =
188f532d61dSAiden Grossman       parseIR(Ctx, "define float @f(float %a) {\n"
189f532d61dSAiden Grossman                    "  %b = call float @llvm.cos.f32(float %a)\n"
190f532d61dSAiden Grossman                    "  ret float %b\n"
191f532d61dSAiden Grossman                    "}\n"
192f532d61dSAiden Grossman                    "declare float @llvm.cos.f32(float)\n");
193f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
194f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
195f532d61dSAiden Grossman }
196f532d61dSAiden Grossman 
197f532d61dSAiden Grossman TEST(StructuralHashTest, CallInstruction) {
198f532d61dSAiden Grossman   LLVMContext Ctx;
199f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i64 @f(i64 %a) {\n"
200f532d61dSAiden Grossman                                             "  %b = call i64 @f1(i64 %a)\n"
201f532d61dSAiden Grossman                                             "  ret i64 %b\n"
202f532d61dSAiden Grossman                                             "}\n"
203f532d61dSAiden Grossman                                             "declare i64 @f1(i64)");
204f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i64 @f(i64 %a) {\n"
205f532d61dSAiden Grossman                                             "  %b = call i64 @f2(i64 %a)\n"
206f532d61dSAiden Grossman                                             "  ret i64 %b\n"
207f532d61dSAiden Grossman                                             "}\n"
208f532d61dSAiden Grossman                                             "declare i64 @f2(i64)");
209f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
210f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
211f532d61dSAiden Grossman }
212f532d61dSAiden Grossman 
213f532d61dSAiden Grossman TEST(StructuralHashTest, ConstantInteger) {
214f532d61dSAiden Grossman   LLVMContext Ctx;
215f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i64 @f1() {\n"
216f532d61dSAiden Grossman                                             "  ret i64 1\n"
217f532d61dSAiden Grossman                                             "}\n");
218f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i64 @f2() {\n"
219f532d61dSAiden Grossman                                             "  ret i64 2\n"
220f532d61dSAiden Grossman                                             "}\n");
221f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
222f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
223f532d61dSAiden Grossman }
224f532d61dSAiden Grossman 
225f532d61dSAiden Grossman TEST(StructuralHashTest, BigConstantInteger) {
226f532d61dSAiden Grossman   LLVMContext Ctx;
227f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i128 @f1() {\n"
228f532d61dSAiden Grossman                                             "  ret i128 18446744073709551616\n"
229f532d61dSAiden Grossman                                             "}\n");
230f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i128 @f2() {\n"
231f532d61dSAiden Grossman                                             "  ret i128 18446744073709551617\n"
232f532d61dSAiden Grossman                                             "}\n");
233f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
234f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
235f532d61dSAiden Grossman }
236f532d61dSAiden Grossman 
237f532d61dSAiden Grossman TEST(StructuralHashTest, ArgumentNumber) {
238f532d61dSAiden Grossman   LLVMContext Ctx;
239f532d61dSAiden Grossman   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i64 @f1(i64 %a, i64 %b) {\n"
240f532d61dSAiden Grossman                                             "  ret i64 %a\n"
241f532d61dSAiden Grossman                                             "}\n");
242f532d61dSAiden Grossman   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i64 @f2(i64 %a, i64 %b) {\n"
243f532d61dSAiden Grossman                                             "  ret i64 %b\n"
244f532d61dSAiden Grossman                                             "}\n");
245f532d61dSAiden Grossman   EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
246f532d61dSAiden Grossman   EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
247f532d61dSAiden Grossman }
248*0dd9fdcfSKyungwoo Lee 
249*0dd9fdcfSKyungwoo Lee TEST(StructuralHashTest, Differences) {
250*0dd9fdcfSKyungwoo Lee   LLVMContext Ctx;
251*0dd9fdcfSKyungwoo Lee   std::unique_ptr<Module> M1 = parseIR(Ctx, "define i64 @f(i64 %a) {\n"
252*0dd9fdcfSKyungwoo Lee                                             "  %c = add i64 %a, 1\n"
253*0dd9fdcfSKyungwoo Lee                                             "  %b = call i64 @f1(i64 %c)\n"
254*0dd9fdcfSKyungwoo Lee                                             "  ret i64 %b\n"
255*0dd9fdcfSKyungwoo Lee                                             "}\n"
256*0dd9fdcfSKyungwoo Lee                                             "declare i64 @f1(i64)");
257*0dd9fdcfSKyungwoo Lee   auto *F1 = M1->getFunction("f");
258*0dd9fdcfSKyungwoo Lee   std::unique_ptr<Module> M2 = parseIR(Ctx, "define i64 @g(i64 %a) {\n"
259*0dd9fdcfSKyungwoo Lee                                             "  %c = add i64 %a, 1\n"
260*0dd9fdcfSKyungwoo Lee                                             "  %b = call i64 @f2(i64 %c)\n"
261*0dd9fdcfSKyungwoo Lee                                             "  ret i64 %b\n"
262*0dd9fdcfSKyungwoo Lee                                             "}\n"
263*0dd9fdcfSKyungwoo Lee                                             "declare i64 @f2(i64)");
264*0dd9fdcfSKyungwoo Lee   auto *F2 = M2->getFunction("g");
265*0dd9fdcfSKyungwoo Lee 
266*0dd9fdcfSKyungwoo Lee   // They are originally different when not ignoring any operand.
267*0dd9fdcfSKyungwoo Lee   EXPECT_NE(StructuralHash(*F1, true), StructuralHash(*F2, true));
268*0dd9fdcfSKyungwoo Lee   EXPECT_NE(StructuralHashWithDifferences(*F1, nullptr).FunctionHash,
269*0dd9fdcfSKyungwoo Lee             StructuralHashWithDifferences(*F2, nullptr).FunctionHash);
270*0dd9fdcfSKyungwoo Lee 
271*0dd9fdcfSKyungwoo Lee   // When we ignore the call target f1 vs f2, they have the same hash.
272*0dd9fdcfSKyungwoo Lee   auto IgnoreOp = [&](const Instruction *I, unsigned OpndIdx) {
273*0dd9fdcfSKyungwoo Lee     return I->getOpcode() == Instruction::Call && OpndIdx == 1;
274*0dd9fdcfSKyungwoo Lee   };
275*0dd9fdcfSKyungwoo Lee   auto FuncHashInfo1 = StructuralHashWithDifferences(*F1, IgnoreOp);
276*0dd9fdcfSKyungwoo Lee   auto FuncHashInfo2 = StructuralHashWithDifferences(*F2, IgnoreOp);
277*0dd9fdcfSKyungwoo Lee   EXPECT_EQ(FuncHashInfo1.FunctionHash, FuncHashInfo2.FunctionHash);
278*0dd9fdcfSKyungwoo Lee 
279*0dd9fdcfSKyungwoo Lee   // There are total 3 instructions.
280*0dd9fdcfSKyungwoo Lee   EXPECT_THAT(*FuncHashInfo1.IndexInstruction, SizeIs(3));
281*0dd9fdcfSKyungwoo Lee   EXPECT_THAT(*FuncHashInfo2.IndexInstruction, SizeIs(3));
282*0dd9fdcfSKyungwoo Lee 
283*0dd9fdcfSKyungwoo Lee   // The only 1 operand (the call target) has been ignored.
284*0dd9fdcfSKyungwoo Lee   EXPECT_THAT(*FuncHashInfo1.IndexOperandHashMap, SizeIs(1u));
285*0dd9fdcfSKyungwoo Lee   EXPECT_THAT(*FuncHashInfo2.IndexOperandHashMap, SizeIs(1u));
286*0dd9fdcfSKyungwoo Lee 
287*0dd9fdcfSKyungwoo Lee   // The index pair of instruction and operand (1, 1) is a key in the map.
288*0dd9fdcfSKyungwoo Lee   ASSERT_THAT(*FuncHashInfo1.IndexOperandHashMap, Contains(Key(Pair(1, 1))));
289*0dd9fdcfSKyungwoo Lee   ASSERT_THAT(*FuncHashInfo2.IndexOperandHashMap, Contains(Key(Pair(1, 1))));
290*0dd9fdcfSKyungwoo Lee 
291*0dd9fdcfSKyungwoo Lee   // The indexed instruciton must be the call instruction as shown in the
292*0dd9fdcfSKyungwoo Lee   // IgnoreOp above.
293*0dd9fdcfSKyungwoo Lee   EXPECT_EQ(FuncHashInfo1.IndexInstruction->lookup(1)->getOpcode(),
294*0dd9fdcfSKyungwoo Lee             Instruction::Call);
295*0dd9fdcfSKyungwoo Lee   EXPECT_EQ(FuncHashInfo2.IndexInstruction->lookup(1)->getOpcode(),
296*0dd9fdcfSKyungwoo Lee             Instruction::Call);
297*0dd9fdcfSKyungwoo Lee 
298*0dd9fdcfSKyungwoo Lee   // The ignored operand hashes (for f1 vs. f2) are different.
299*0dd9fdcfSKyungwoo Lee   EXPECT_NE(FuncHashInfo1.IndexOperandHashMap->lookup({1, 1}),
300*0dd9fdcfSKyungwoo Lee             FuncHashInfo2.IndexOperandHashMap->lookup({1, 1}));
301*0dd9fdcfSKyungwoo Lee }
302*0dd9fdcfSKyungwoo Lee 
303bdbb3fd5SArthur Eubanks } // end anonymous namespace
304