1 //===- llvm/unittest/IR/StructuralHashTest.cpp ----------------------------===// 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 #include "llvm/IR/StructuralHash.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/IR/Module.h" 12 #include "llvm/Support/SourceMgr.h" 13 #include "gtest/gtest.h" 14 15 #include <memory> 16 17 using namespace llvm; 18 19 namespace { 20 21 std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) { 22 SMDiagnostic Err; 23 std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Context); 24 if (!M) 25 Err.print("StructuralHashTest", errs()); 26 return M; 27 } 28 29 TEST(StructuralHashTest, Empty) { 30 LLVMContext Ctx; 31 std::unique_ptr<Module> M1 = parseIR(Ctx, ""); 32 std::unique_ptr<Module> M2 = parseIR(Ctx, ""); 33 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2)); 34 } 35 36 TEST(StructuralHashTest, Basic) { 37 LLVMContext Ctx; 38 std::unique_ptr<Module> M0 = parseIR(Ctx, ""); 39 std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }"); 40 std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f() { ret void }"); 41 std::unique_ptr<Module> M3 = parseIR(Ctx, "@g = global i32 2"); 42 std::unique_ptr<Module> M4 = parseIR(Ctx, "@g = global i32 2"); 43 EXPECT_NE(StructuralHash(*M0), StructuralHash(*M1)); 44 EXPECT_NE(StructuralHash(*M0), StructuralHash(*M3)); 45 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M3)); 46 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2)); 47 EXPECT_EQ(StructuralHash(*M3), StructuralHash(*M4)); 48 } 49 50 TEST(StructuralHashTest, BasicFunction) { 51 LLVMContext Ctx; 52 std::unique_ptr<Module> M = parseIR(Ctx, "define void @f() {\n" 53 " ret void\n" 54 "}\n" 55 "define void @g() {\n" 56 " ret void\n" 57 "}\n" 58 "define i32 @h(i32 %i) {\n" 59 " ret i32 %i\n" 60 "}\n"); 61 EXPECT_EQ(StructuralHash(*M->getFunction("f")), 62 StructuralHash(*M->getFunction("g"))); 63 EXPECT_NE(StructuralHash(*M->getFunction("f")), 64 StructuralHash(*M->getFunction("h"))); 65 } 66 67 TEST(StructuralHashTest, Declaration) { 68 LLVMContext Ctx; 69 std::unique_ptr<Module> M0 = parseIR(Ctx, ""); 70 std::unique_ptr<Module> M1 = parseIR(Ctx, "declare void @f()"); 71 std::unique_ptr<Module> M2 = parseIR(Ctx, "@g = external global i32"); 72 EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M1)); 73 EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M2)); 74 } 75 76 TEST(StructuralHashTest, GlobalType) { 77 LLVMContext Ctx; 78 std::unique_ptr<Module> M1 = parseIR(Ctx, "@g = global i32 1"); 79 std::unique_ptr<Module> M2 = parseIR(Ctx, "@g = global float 1.0"); 80 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2)); 81 } 82 83 TEST(StructuralHashTest, Function) { 84 LLVMContext Ctx; 85 std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }"); 86 std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f(i32) { ret void }"); 87 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2)); 88 } 89 90 TEST(StructuralHashTest, FunctionRetType) { 91 LLVMContext Ctx; 92 std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f() { ret void }"); 93 std::unique_ptr<Module> M2 = parseIR(Ctx, "define i32 @f() { ret i32 0 }"); 94 // FIXME: should be different 95 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2)); 96 } 97 98 TEST(StructuralHashTest, InstructionOpCode) { 99 LLVMContext Ctx; 100 std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f(ptr %p) {\n" 101 " %a = load i32, ptr %p\n" 102 " ret void\n" 103 "}\n"); 104 std::unique_ptr<Module> M2 = 105 parseIR(Ctx, "define void @f(ptr %p) {\n" 106 " %a = getelementptr i8, ptr %p, i32 1\n" 107 " ret void\n" 108 "}\n"); 109 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2)); 110 } 111 112 TEST(StructuralHashTest, InstructionType) { 113 LLVMContext Ctx; 114 std::unique_ptr<Module> M1 = parseIR(Ctx, "define void @f(ptr %p) {\n" 115 " %a = load i32, ptr %p\n" 116 " ret void\n" 117 "}\n"); 118 std::unique_ptr<Module> M2 = parseIR(Ctx, "define void @f(ptr %p) {\n" 119 " %a = load i64, ptr %p\n" 120 " ret void\n" 121 "}\n"); 122 // FIXME: should be different 123 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2)); 124 } 125 126 TEST(StructuralHashTest, IgnoredMetadata) { 127 LLVMContext Ctx; 128 std::unique_ptr<Module> M1 = parseIR(Ctx, "@a = global i32 1\n"); 129 // clang-format off 130 std::unique_ptr<Module> M2 = parseIR( 131 Ctx, R"( 132 @a = global i32 1 133 @llvm.embedded.object = private constant [4 x i8] c"BC\C0\00", section ".llvm.lto", align 1, !exclude !0 134 @llvm.compiler.used = appending global [1 x ptr] [ptr @llvm.embedded.object], section "llvm.metadata" 135 136 !llvm.embedded.objects = !{!1} 137 138 !0 = !{} 139 !1 = !{ptr @llvm.embedded.object, !".llvm.lto"} 140 )"); 141 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2)); 142 } 143 } // end anonymous namespace 144