xref: /llvm-project/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp (revision 4ec55f8ab6f172bfe38e4ca89bfd0747e166995b)
1 //===- ValueMapper.cpp - Unit tests for ValueMapper -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/IR/Constants.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Metadata.h"
14 #include "llvm/Transforms/Utils/ValueMapper.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 
19 namespace {
20 
21 TEST(ValueMapperTest, MapMetadata) {
22   LLVMContext Context;
23   auto *U = MDTuple::get(Context, None);
24 
25   // The node should be unchanged.
26   ValueToValueMapTy VM;
27   EXPECT_EQ(U, MapMetadata(U, VM, RF_None));
28 }
29 
30 TEST(ValueMapperTest, MapMetadataCycle) {
31   LLVMContext Context;
32   MDNode *U0;
33   MDNode *U1;
34   {
35     Metadata *Ops[] = {nullptr};
36     auto T = MDTuple::getTemporary(Context, Ops);
37     Ops[0] = T.get();
38     U0 = MDTuple::get(Context, Ops);
39     T->replaceOperandWith(0, U0);
40     U1 = MDNode::replaceWithUniqued(std::move(T));
41     U0->resolveCycles();
42   }
43 
44   EXPECT_TRUE(U0->isResolved());
45   EXPECT_TRUE(U0->isUniqued());
46   EXPECT_TRUE(U1->isResolved());
47   EXPECT_TRUE(U1->isUniqued());
48   EXPECT_EQ(U1, U0->getOperand(0));
49   EXPECT_EQ(U0, U1->getOperand(0));
50 
51   // Cycles shouldn't be duplicated.
52   {
53     ValueToValueMapTy VM;
54     EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
55     EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
56   }
57 
58   // Check the other order.
59   {
60     ValueToValueMapTy VM;
61     EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
62     EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
63   }
64 }
65 
66 TEST(ValueMapperTest, MapMetadataUnresolved) {
67   LLVMContext Context;
68   TempMDTuple T = MDTuple::getTemporary(Context, None);
69 
70   ValueToValueMapTy VM;
71   EXPECT_EQ(T.get(), MapMetadata(T.get(), VM, RF_NoModuleLevelChanges));
72 }
73 
74 TEST(ValueMapperTest, MapMetadataDistinct) {
75   LLVMContext Context;
76   auto *D = MDTuple::getDistinct(Context, None);
77 
78   {
79     // The node should be cloned.
80     ValueToValueMapTy VM;
81     EXPECT_NE(D, MapMetadata(D, VM, RF_None));
82   }
83   {
84     // The node should be moved.
85     ValueToValueMapTy VM;
86     EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
87   }
88 }
89 
90 TEST(ValueMapperTest, MapMetadataDistinctOperands) {
91   LLVMContext Context;
92   Metadata *Old = MDTuple::getDistinct(Context, None);
93   auto *D = MDTuple::getDistinct(Context, Old);
94   ASSERT_EQ(Old, D->getOperand(0));
95 
96   Metadata *New = MDTuple::getDistinct(Context, None);
97   ValueToValueMapTy VM;
98   VM.MD()[Old].reset(New);
99 
100   // Make sure operands are updated.
101   EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
102   EXPECT_EQ(New, D->getOperand(0));
103 }
104 
105 TEST(ValueMapperTest, MapMetadataSeeded) {
106   LLVMContext Context;
107   auto *D = MDTuple::getDistinct(Context, None);
108 
109   // The node should be moved.
110   ValueToValueMapTy VM;
111   EXPECT_EQ(None, VM.getMappedMD(D));
112 
113   VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
114   EXPECT_EQ(D, *VM.getMappedMD(D));
115   EXPECT_EQ(D, MapMetadata(D, VM, RF_None));
116 }
117 
118 TEST(ValueMapperTest, MapMetadataSeededWithNull) {
119   LLVMContext Context;
120   auto *D = MDTuple::getDistinct(Context, None);
121 
122   // The node should be moved.
123   ValueToValueMapTy VM;
124   EXPECT_EQ(None, VM.getMappedMD(D));
125 
126   VM.MD().insert(std::make_pair(D, TrackingMDRef()));
127   EXPECT_EQ(nullptr, *VM.getMappedMD(D));
128   EXPECT_EQ(nullptr, MapMetadata(D, VM, RF_None));
129 }
130 
131 TEST(ValueMapperTest, MapMetadataNullMapGlobalWithIgnoreMissingLocals) {
132   LLVMContext C;
133   FunctionType *FTy =
134       FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
135   std::unique_ptr<Function> F(
136       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
137 
138   ValueToValueMapTy VM;
139   RemapFlags Flags = RF_IgnoreMissingLocals | RF_NullMapMissingGlobalValues;
140   EXPECT_EQ(nullptr, MapValue(F.get(), VM, Flags));
141 }
142 
143 TEST(ValueMapperTest, MapMetadataConstantAsMetadata) {
144   LLVMContext C;
145   FunctionType *FTy =
146       FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
147   std::unique_ptr<Function> F(
148       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
149 
150   auto *CAM = ConstantAsMetadata::get(F.get());
151   {
152     ValueToValueMapTy VM;
153     EXPECT_EQ(CAM, MapMetadata(CAM, VM));
154     EXPECT_TRUE(VM.MD().count(CAM));
155     VM.MD().erase(CAM);
156     EXPECT_EQ(CAM, MapMetadata(CAM, VM, RF_IgnoreMissingLocals));
157     EXPECT_TRUE(VM.MD().count(CAM));
158 
159     auto *N = MDTuple::get(C, None);
160     VM.MD()[CAM].reset(N);
161     EXPECT_EQ(N, MapMetadata(CAM, VM));
162     EXPECT_EQ(N, MapMetadata(CAM, VM, RF_IgnoreMissingLocals));
163   }
164 
165   std::unique_ptr<Function> F2(
166       Function::Create(FTy, GlobalValue::ExternalLinkage, "F2"));
167   ValueToValueMapTy VM;
168   VM[F.get()] = F2.get();
169   auto *F2MD = MapMetadata(CAM, VM);
170   EXPECT_TRUE(VM.MD().count(CAM));
171   EXPECT_TRUE(F2MD);
172   EXPECT_EQ(F2.get(), cast<ConstantAsMetadata>(F2MD)->getValue());
173 }
174 
175 #ifdef GTEST_HAS_DEATH_TEST
176 #ifndef NDEBUG
177 TEST(ValueMapperTest, MapMetadataLocalAsMetadata) {
178   LLVMContext C;
179   FunctionType *FTy =
180       FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
181   std::unique_ptr<Function> F(
182       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
183   Argument &A = *F->arg_begin();
184 
185   // MapMetadata doesn't support LocalAsMetadata.  The only valid container for
186   // LocalAsMetadata is a MetadataAsValue instance, so use it directly.
187   auto *LAM = LocalAsMetadata::get(&A);
188   ValueToValueMapTy VM;
189   EXPECT_DEATH(MapMetadata(LAM, VM), "Unexpected local metadata");
190   EXPECT_DEATH(MapMetadata(LAM, VM, RF_IgnoreMissingLocals),
191                "Unexpected local metadata");
192 }
193 #endif
194 #endif
195 
196 TEST(ValueMapperTest, MapValueLocalAsMetadata) {
197   LLVMContext C;
198   FunctionType *FTy =
199       FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
200   std::unique_ptr<Function> F(
201       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
202   Argument &A = *F->arg_begin();
203 
204   auto *LAM = LocalAsMetadata::get(&A);
205   auto *MAV = MetadataAsValue::get(C, LAM);
206 
207   // The principled answer to a LocalAsMetadata of an unmapped SSA value would
208   // be to return nullptr (regardless of RF_IgnoreMissingLocals).
209   //
210   // However, algorithms that use RemapInstruction assume that each instruction
211   // only references SSA values from previous instructions.  Arguments of
212   // such as "metadata i32 %x" don't currently successfully maintain that
213   // property.  To keep RemapInstruction from crashing we need a non-null
214   // return here, but we also shouldn't reference the unmapped local.  Use
215   // "metadata !{}".
216   auto *N0 = MDTuple::get(C, None);
217   auto *N0AV = MetadataAsValue::get(C, N0);
218   ValueToValueMapTy VM;
219   EXPECT_EQ(N0AV, MapValue(MAV, VM));
220   EXPECT_EQ(nullptr, MapValue(MAV, VM, RF_IgnoreMissingLocals));
221   EXPECT_FALSE(VM.count(MAV));
222   EXPECT_FALSE(VM.count(&A));
223   EXPECT_EQ(None, VM.getMappedMD(LAM));
224 
225   VM[MAV] = MAV;
226   EXPECT_EQ(MAV, MapValue(MAV, VM));
227   EXPECT_EQ(MAV, MapValue(MAV, VM, RF_IgnoreMissingLocals));
228   EXPECT_TRUE(VM.count(MAV));
229   EXPECT_FALSE(VM.count(&A));
230 
231   VM[MAV] = &A;
232   EXPECT_EQ(&A, MapValue(MAV, VM));
233   EXPECT_EQ(&A, MapValue(MAV, VM, RF_IgnoreMissingLocals));
234   EXPECT_TRUE(VM.count(MAV));
235   EXPECT_FALSE(VM.count(&A));
236 }
237 
238 TEST(ValueMapperTest, MapValueLocalAsMetadataToConstant) {
239   LLVMContext Context;
240   auto *Int8 = Type::getInt8Ty(Context);
241   FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Int8, false);
242   std::unique_ptr<Function> F(
243       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
244 
245   // Map a local value to a constant.
246   Argument &A = *F->arg_begin();
247   Constant &C = *ConstantInt::get(Int8, 42);
248   ValueToValueMapTy VM;
249   VM[&A] = &C;
250 
251   // Look up the metadata-as-value wrapper.  Don't crash.
252   auto *MDA = MetadataAsValue::get(Context, ValueAsMetadata::get(&A));
253   auto *MDC = MetadataAsValue::get(Context, ValueAsMetadata::get(&C));
254   EXPECT_TRUE(isa<LocalAsMetadata>(MDA->getMetadata()));
255   EXPECT_TRUE(isa<ConstantAsMetadata>(MDC->getMetadata()));
256   EXPECT_EQ(&C, MapValue(&A, VM));
257   EXPECT_EQ(MDC, MapValue(MDA, VM));
258 }
259 
260 } // end namespace
261