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
17using namespace llvm;
18
19namespace {
20
21std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
22 SMDiagnostic Err;
23 std::unique_ptr<Module> M = parseAssemblyString(AsmString: IR, Err, Context);
24 if (!M)
25 Err.print(ProgName: "StructuralHashTest", S&: errs());
26 return M;
27}
28
29TEST(StructuralHashTest, Empty) {
30 LLVMContext Ctx;
31 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "");
32 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "");
33 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
34}
35
36TEST(StructuralHashTest, Basic) {
37 LLVMContext Ctx;
38 std::unique_ptr<Module> M0 = parseIR(Context&: Ctx, IR: "");
39 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define void @f() { ret void }");
40 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define void @f() { ret void }");
41 std::unique_ptr<Module> M3 = parseIR(Context&: Ctx, IR: "@g = global i32 2");
42 std::unique_ptr<Module> M4 = parseIR(Context&: Ctx, IR: "@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
50TEST(StructuralHashTest, BasicFunction) {
51 LLVMContext Ctx;
52 std::unique_ptr<Module> M = parseIR(Context&: Ctx, IR: "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
67TEST(StructuralHashTest, Declaration) {
68 LLVMContext Ctx;
69 std::unique_ptr<Module> M0 = parseIR(Context&: Ctx, IR: "");
70 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "declare void @f()");
71 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "@g = external global i32");
72 EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M1));
73 EXPECT_EQ(StructuralHash(*M0), StructuralHash(*M2));
74}
75
76TEST(StructuralHashTest, GlobalType) {
77 LLVMContext Ctx;
78 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "@g = global i32 1");
79 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "@g = global float 1.0");
80 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2));
81}
82
83TEST(StructuralHashTest, Function) {
84 LLVMContext Ctx;
85 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define void @f() { ret void }");
86 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define void @f(i32) { ret void }");
87 EXPECT_NE(StructuralHash(*M1), StructuralHash(*M2));
88}
89
90TEST(StructuralHashTest, FunctionRetType) {
91 LLVMContext Ctx;
92 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define void @f() { ret void }");
93 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i32 @f() { ret i32 0 }");
94 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
95 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
96}
97
98TEST(StructuralHashTest, InstructionOpCode) {
99 LLVMContext Ctx;
100 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "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(Context&: Ctx, IR: "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
112TEST(StructuralHashTest, InstructionSubType) {
113 LLVMContext Ctx;
114 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "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(Context&: Ctx, IR: "define void @f(ptr %p) {\n"
119 " %a = load i64, ptr %p\n"
120 " ret void\n"
121 "}\n");
122 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
123 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
124}
125
126TEST(StructuralHashTest, InstructionType) {
127 LLVMContext Ctx;
128 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define void @f(ptr %p) {\n"
129 " %1 = load i32, ptr %p\n"
130 " ret void\n"
131 "}\n");
132 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define void @f(ptr %p) {\n"
133 " %1 = load float, ptr %p\n"
134 " ret void\n"
135 "}\n");
136 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
137 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
138}
139
140TEST(StructuralHashTest, IgnoredMetadata) {
141 LLVMContext Ctx;
142 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "@a = global i32 1\n");
143 // clang-format off
144 std::unique_ptr<Module> M2 = parseIR(
145 Context&: Ctx, IR: R"(
146 @a = global i32 1
147 @llvm.embedded.object = private constant [4 x i8] c"BC\C0\00", section ".llvm.lto", align 1, !exclude !0
148 @llvm.compiler.used = appending global [1 x ptr] [ptr @llvm.embedded.object], section "llvm.metadata"
149
150 !llvm.embedded.objects = !{!1}
151
152 !0 = !{}
153 !1 = !{ptr @llvm.embedded.object, !".llvm.lto"}
154 )");
155 // clang-format on
156 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
157}
158
159TEST(StructuralHashTest, ComparisonInstructionPredicate) {
160 LLVMContext Ctx;
161 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define i1 @f(i64 %a, i64 %b) {\n"
162 " %1 = icmp eq i64 %a, %b\n"
163 " ret i1 %1\n"
164 "}\n");
165 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i1 @f(i64 %a, i64 %b) {\n"
166 " %1 = icmp ne i64 %a, %b\n"
167 " ret i1 %1\n"
168 "}\n");
169 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
170 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
171}
172
173TEST(StructuralHashTest, IntrinsicInstruction) {
174 LLVMContext Ctx;
175 std::unique_ptr<Module> M1 =
176 parseIR(Context&: Ctx, IR: "define float @f(float %a) {\n"
177 " %b = call float @llvm.sin.f32(float %a)\n"
178 " ret float %b\n"
179 "}\n"
180 "declare float @llvm.sin.f32(float)\n");
181 std::unique_ptr<Module> M2 =
182 parseIR(Context&: Ctx, IR: "define float @f(float %a) {\n"
183 " %b = call float @llvm.cos.f32(float %a)\n"
184 " ret float %b\n"
185 "}\n"
186 "declare float @llvm.cos.f32(float)\n");
187 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
188 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
189}
190
191TEST(StructuralHashTest, CallInstruction) {
192 LLVMContext Ctx;
193 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define i64 @f(i64 %a) {\n"
194 " %b = call i64 @f1(i64 %a)\n"
195 " ret i64 %b\n"
196 "}\n"
197 "declare i64 @f1(i64)");
198 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i64 @f(i64 %a) {\n"
199 " %b = call i64 @f2(i64 %a)\n"
200 " ret i64 %b\n"
201 "}\n"
202 "declare i64 @f2(i64)");
203 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
204 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
205}
206
207TEST(StructuralHashTest, ConstantInteger) {
208 LLVMContext Ctx;
209 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define i64 @f1() {\n"
210 " ret i64 1\n"
211 "}\n");
212 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i64 @f2() {\n"
213 " ret i64 2\n"
214 "}\n");
215 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
216 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
217}
218
219TEST(StructuralHashTest, BigConstantInteger) {
220 LLVMContext Ctx;
221 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define i128 @f1() {\n"
222 " ret i128 18446744073709551616\n"
223 "}\n");
224 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i128 @f2() {\n"
225 " ret i128 18446744073709551617\n"
226 "}\n");
227 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
228 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
229}
230
231TEST(StructuralHashTest, ArgumentNumber) {
232 LLVMContext Ctx;
233 std::unique_ptr<Module> M1 = parseIR(Context&: Ctx, IR: "define i64 @f1(i64 %a, i64 %b) {\n"
234 " ret i64 %a\n"
235 "}\n");
236 std::unique_ptr<Module> M2 = parseIR(Context&: Ctx, IR: "define i64 @f2(i64 %a, i64 %b) {\n"
237 " ret i64 %b\n"
238 "}\n");
239 EXPECT_EQ(StructuralHash(*M1), StructuralHash(*M2));
240 EXPECT_NE(StructuralHash(*M1, true), StructuralHash(*M2, true));
241}
242} // end anonymous namespace
243

source code of llvm/unittests/IR/StructuralHashTest.cpp