mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-13 19:40:26 +00:00
ValueMapper: Resolve cycles on the new nodes
Fix a major bug from r265456. Although it's now much rarer, ValueMapper sometimes has to duplicate cycles. The might-transitively-reference-a-temporary counts don't decrement on their own when there are cycles, and you need to call MDNode::resolveCycles to fix it. r265456 was checking the input nodes to see if they were unresolved. This is useless; they should never be unresolved. Instead we should check the output nodes and resolve cycles on them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266258 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2af3e8f798
commit
4cd20e7e7d
@ -587,6 +587,7 @@ void MDNodeMapper::mapDistinctNodes() {
|
|||||||
|
|
||||||
void MDNodeMapper::mapUniquedNodes() {
|
void MDNodeMapper::mapUniquedNodes() {
|
||||||
// Construct uniqued nodes, building forward references as necessary.
|
// Construct uniqued nodes, building forward references as necessary.
|
||||||
|
SmallVector<MDNode *, 16> CyclicNodes;
|
||||||
for (auto *N : POT) {
|
for (auto *N : POT) {
|
||||||
if (N->isDistinct())
|
if (N->isDistinct())
|
||||||
continue;
|
continue;
|
||||||
@ -601,11 +602,12 @@ void MDNodeMapper::mapUniquedNodes() {
|
|||||||
|
|
||||||
TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone();
|
TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone();
|
||||||
remapOperands(D, *ClonedN);
|
remapOperands(D, *ClonedN);
|
||||||
M.mapToMetadata(N, MDNode::replaceWithUniqued(std::move(ClonedN)));
|
CyclicNodes.push_back(MDNode::replaceWithUniqued(std::move(ClonedN)));
|
||||||
|
M.mapToMetadata(N, CyclicNodes.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve cycles.
|
// Resolve cycles.
|
||||||
for (auto *N : POT)
|
for (auto *N : CyclicNodes)
|
||||||
if (!N->isResolved())
|
if (!N->isResolved())
|
||||||
N->resolveCycles();
|
N->resolveCycles();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
#include "llvm/IR/Metadata.h"
|
#include "llvm/IR/Metadata.h"
|
||||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||||
@ -63,6 +64,47 @@ TEST(ValueMapperTest, MapMetadataCycle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ValueMapperTest, MapMetadataDuplicatedCycle) {
|
||||||
|
LLVMContext Context;
|
||||||
|
auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
|
||||||
|
std::unique_ptr<GlobalVariable> G0 = llvm::make_unique<GlobalVariable>(
|
||||||
|
PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G0");
|
||||||
|
std::unique_ptr<GlobalVariable> G1 = llvm::make_unique<GlobalVariable>(
|
||||||
|
PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G1");
|
||||||
|
|
||||||
|
// Create a cycle that references G0.
|
||||||
|
MDNode *N0; // !0 = !{!1}
|
||||||
|
MDNode *N1; // !1 = !{!0, i8* @G0}
|
||||||
|
{
|
||||||
|
auto T0 = MDTuple::getTemporary(Context, nullptr);
|
||||||
|
Metadata *Ops1[] = {T0.get(), ConstantAsMetadata::get(G0.get())};
|
||||||
|
N1 = MDTuple::get(Context, Ops1);
|
||||||
|
T0->replaceOperandWith(0, N1);
|
||||||
|
N0 = MDNode::replaceWithUniqued(std::move(T0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve N0 and N1.
|
||||||
|
ASSERT_FALSE(N0->isResolved());
|
||||||
|
ASSERT_FALSE(N1->isResolved());
|
||||||
|
N0->resolveCycles();
|
||||||
|
ASSERT_TRUE(N0->isResolved());
|
||||||
|
ASSERT_TRUE(N1->isResolved());
|
||||||
|
|
||||||
|
// Seed the value map to map G0 to G1 and map the nodes. The output should
|
||||||
|
// have new nodes that reference G1 (instead of G0).
|
||||||
|
ValueToValueMapTy VM;
|
||||||
|
VM[G0.get()] = G1.get();
|
||||||
|
MDNode *MappedN0 = MapMetadata(N0, VM);
|
||||||
|
MDNode *MappedN1 = MapMetadata(N1, VM);
|
||||||
|
EXPECT_NE(N0, MappedN0);
|
||||||
|
EXPECT_NE(N1, MappedN1);
|
||||||
|
EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
|
||||||
|
|
||||||
|
// Check that the output nodes are resolved.
|
||||||
|
EXPECT_TRUE(MappedN0->isResolved());
|
||||||
|
EXPECT_TRUE(MappedN1->isResolved());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, MapMetadataUnresolved) {
|
TEST(ValueMapperTest, MapMetadataUnresolved) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
TempMDTuple T = MDTuple::getTemporary(Context, None);
|
TempMDTuple T = MDTuple::getTemporary(Context, None);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user