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