xref: /llvm-project/llvm/unittests/MIR/MachineStableHashTest.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1 //===- MachineStableHashTest.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/CodeGen/MachineStableHash.h"
10 #include "llvm/CodeGen/MIRParser/MIRParser.h"
11 #include "llvm/CodeGen/MachineFunction.h"
12 #include "llvm/CodeGen/MachineModuleInfo.h"
13 #include "llvm/FileCheck/FileCheck.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/TargetSelect.h"
18 #include "llvm/Target/TargetMachine.h"
19 #include "gtest/gtest.h"
20 
21 using namespace llvm;
22 
23 class MachineStableHashTest : public testing::Test {
24 public:
25   MachineStableHashTest() {}
26 
27 protected:
28   LLVMContext Context;
29   std::unique_ptr<Module> M;
30   std::unique_ptr<MIRParser> MIR;
31 
32   static void SetUpTestCase() {
33     InitializeAllTargetInfos();
34     InitializeAllTargets();
35     InitializeAllTargetMCs();
36   }
37 
38   void SetUp() override { M = std::make_unique<Module>("Dummy", Context); }
39 
40   std::unique_ptr<TargetMachine>
41   createTargetMachine(std::string TT, StringRef CPU, StringRef FS) {
42     std::string Error;
43     const Target *T = TargetRegistry::lookupTarget(TT, Error);
44     if (!T)
45       return nullptr;
46     TargetOptions Options;
47     return std::unique_ptr<TargetMachine>(T->createTargetMachine(
48         TT, CPU, FS, Options, std::nullopt, std::nullopt));
49   }
50 
51   std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode,
52                                    MachineModuleInfo &MMI) {
53     SMDiagnostic Diagnostic;
54     std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
55     MIR = createMIRParser(std::move(MBuffer), Context);
56     if (!MIR)
57       return nullptr;
58 
59     std::unique_ptr<Module> Mod = MIR->parseIRModule();
60     if (!Mod)
61       return nullptr;
62 
63     Mod->setDataLayout(TM.createDataLayout());
64 
65     if (MIR->parseMachineFunctions(*Mod, MMI)) {
66       M.reset();
67       return nullptr;
68     }
69 
70     return Mod;
71   }
72 };
73 
74 TEST_F(MachineStableHashTest, StableGlobalName) {
75   auto TM = createTargetMachine(("aarch64--"), "", "");
76   if (!TM)
77     GTEST_SKIP();
78   StringRef MIRString = R"MIR(
79 --- |
80   define void @f1() { ret void }
81   define void @f2() { ret void }
82   define void @f3() { ret void }
83   define void @f4() { ret void }
84   declare void @goo()
85   declare void @goo.llvm.123()
86   declare void @goo.__uniq.456()
87   declare void @goo.invalid.789()
88 ...
89 ---
90 name:            f1
91 alignment:       16
92 tracksRegLiveness: true
93 frameInfo:
94   maxAlignment:    16
95 machineFunctionInfo: {}
96 body:             |
97   bb.0:
98   liveins: $lr
99     BL @goo
100   RET undef $lr
101 
102 ...
103 ---
104 name:            f2
105 body:             |
106   bb.0:
107   liveins: $lr
108     BL @goo.llvm.123
109   RET undef $lr
110 ...
111 ---
112 name:            f3
113 body:             |
114   bb.0:
115   liveins: $lr
116     BL @goo.__uniq.456
117   RET undef $lr
118 ...
119 ---
120 name:            f4
121 body:             |
122   bb.0:
123   liveins: $lr
124     BL @goo.invalid.789
125   RET undef $lr
126 ...
127 )MIR";
128   MachineModuleInfo MMI(TM.get());
129   M = parseMIR(*TM, MIRString, MMI);
130   ASSERT_TRUE(M);
131   auto *MF1 = MMI.getMachineFunction(*M->getFunction("f1"));
132   auto *MF2 = MMI.getMachineFunction(*M->getFunction("f2"));
133   auto *MF3 = MMI.getMachineFunction(*M->getFunction("f3"));
134   auto *MF4 = MMI.getMachineFunction(*M->getFunction("f4"));
135 
136   EXPECT_EQ(stableHashValue(*MF1), stableHashValue(*MF2))
137       << "Expect the suffix, `.llvm.{number}` to be ignored.";
138   EXPECT_EQ(stableHashValue(*MF1), stableHashValue(*MF3))
139       << "Expect the suffix, `.__uniq.{number}` to be ignored.";
140   // Do not ignore `.invalid.{number}`.
141   EXPECT_NE(stableHashValue(*MF1), stableHashValue(*MF4));
142 }
143 
144 TEST_F(MachineStableHashTest, ContentName) {
145   auto TM = createTargetMachine(("aarch64--"), "", "");
146   if (!TM)
147     GTEST_SKIP();
148   StringRef MIRString = R"MIR(
149 --- |
150   define void @f1() { ret void }
151   define void @f2() { ret void }
152   define void @f3() { ret void }
153   define void @f4() { ret void }
154   declare void @goo()
155   declare void @goo.content.123()
156   declare void @zoo.content.123()
157   declare void @goo.content.456()
158 ...
159 ---
160 name:            f1
161 alignment:       16
162 tracksRegLiveness: true
163 frameInfo:
164   maxAlignment:    16
165 machineFunctionInfo: {}
166 body:             |
167   bb.0:
168   liveins: $lr
169     BL @goo
170   RET undef $lr
171 ...
172 ---
173 name:            f2
174 body:             |
175   bb.0:
176   liveins: $lr
177     BL @goo.content.123
178   RET undef $lr
179 ...
180 ---
181 name:            f3
182 body:             |
183   bb.0:
184   liveins: $lr
185     BL @zoo.content.123
186   RET undef $lr
187 ...
188 ---
189 name:            f4
190 body:             |
191   bb.0:
192   liveins: $lr
193     BL @goo.content.456
194   RET undef $lr
195 ...
196 )MIR";
197   MachineModuleInfo MMI(TM.get());
198   M = parseMIR(*TM, MIRString, MMI);
199   ASSERT_TRUE(M);
200   auto *MF1 = MMI.getMachineFunction(*M->getFunction("f1"));
201   auto *MF2 = MMI.getMachineFunction(*M->getFunction("f2"));
202   auto *MF3 = MMI.getMachineFunction(*M->getFunction("f3"));
203   auto *MF4 = MMI.getMachineFunction(*M->getFunction("f4"));
204 
205   // Do not ignore `.content.{number}`.
206   EXPECT_NE(stableHashValue(*MF1), stableHashValue(*MF2));
207   EXPECT_EQ(stableHashValue(*MF2), stableHashValue(*MF3))
208       << "Expect the same hash for the same suffix, `.content.{number}`";
209   // Different suffixes should result in different hashes.
210   EXPECT_NE(stableHashValue(*MF2), stableHashValue(*MF4));
211   EXPECT_NE(stableHashValue(*MF3), stableHashValue(*MF4));
212 }
213