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