2015-03-17 09:14:40 +08:00
|
|
|
//===- ValueMapper.cpp - Unit tests for ValueMapper -----------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
|
|
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
ValueMapper: Rewrite Mapper::mapMetadata without recursion
This commit completely rewrites Mapper::mapMetadata (the implementation
of llvm::MapMetadata) using an iterative algorithm. The guts of the new
algorithm are in MDNodeMapper::map, the entry function in a new class.
Previously, Mapper::mapMetadata performed a recursive exploration of the
graph with eager "just in case there's a reason" malloc traffic.
The new algorithm has these benefits:
- New nodes and temporaries are not created eagerly.
- Uniquing cycles are not duplicated (see new unit test).
- No recursion.
Given a node to map, it does this:
1. Use a worklist to perform a post-order traversal of the transitively
referenced unmapped nodes.
2. Track which nodes will change operands, and which will have new
addresses in the mapped scheme. Propagate the changes through the
POT until fixed point, to pick up uniquing cycles that need to
change.
3. Map all the distinct nodes without touching their operands. If
RF_MoveDistinctMetadata, they get mapped to themselves; otherwise,
they get mapped to clones.
4. Map the uniqued nodes (bottom-up), lazily creating temporaries for
forward references as needed.
5. Remap the operands of the distinct nodes.
Mehdi helped me out by profiling this with -flto=thin. On his workload
(importing/etc. for opt.cpp), MapMetadata sped up by 15%, contributed
about 50% less to persistent memory, and made about 100x fewer calls to
malloc. The speedup is less than I'd hoped. The profile mainly blames
DenseMap lookups; perhaps there's a way to reduce them (e.g., by
disallowing remapping of MDString).
It would be nice to break the strange remaining recursion on the Value
side: MapValue => materializeInitFor => RemapInstruction => MapValue. I
think we could do this by having materializeInitFor return a worklist of
things to be remapped.
llvm-svn: 265456
2016-04-06 04:23:21 +08:00
|
|
|
TEST(ValueMapperTest, MapMetadata) {
|
|
|
|
LLVMContext Context;
|
|
|
|
auto *U = MDTuple::get(Context, None);
|
|
|
|
|
|
|
|
// The node should be unchanged.
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(U, MapMetadata(U, VM, RF_None));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ValueMapperTest, MapMetadataCycle) {
|
|
|
|
LLVMContext Context;
|
|
|
|
MDNode *U0;
|
|
|
|
MDNode *U1;
|
|
|
|
{
|
|
|
|
Metadata *Ops[] = {nullptr};
|
|
|
|
auto T = MDTuple::getTemporary(Context, Ops);
|
|
|
|
Ops[0] = T.get();
|
|
|
|
U0 = MDTuple::get(Context, Ops);
|
|
|
|
T->replaceOperandWith(0, U0);
|
|
|
|
U1 = MDNode::replaceWithUniqued(std::move(T));
|
|
|
|
U0->resolveCycles();
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPECT_TRUE(U0->isResolved());
|
|
|
|
EXPECT_TRUE(U0->isUniqued());
|
|
|
|
EXPECT_TRUE(U1->isResolved());
|
|
|
|
EXPECT_TRUE(U1->isUniqued());
|
|
|
|
EXPECT_EQ(U1, U0->getOperand(0));
|
|
|
|
EXPECT_EQ(U0, U1->getOperand(0));
|
|
|
|
|
|
|
|
// Cycles shouldn't be duplicated.
|
|
|
|
{
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
|
|
|
|
EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the other order.
|
|
|
|
{
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
|
|
|
|
EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 09:14:40 +08:00
|
|
|
TEST(ValueMapperTest, MapMetadataUnresolved) {
|
|
|
|
LLVMContext Context;
|
|
|
|
TempMDTuple T = MDTuple::getTemporary(Context, None);
|
|
|
|
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(T.get(), MapMetadata(T.get(), VM, RF_NoModuleLevelChanges));
|
|
|
|
}
|
|
|
|
|
2015-08-04 01:09:38 +08:00
|
|
|
TEST(ValueMapperTest, MapMetadataDistinct) {
|
|
|
|
LLVMContext Context;
|
|
|
|
auto *D = MDTuple::getDistinct(Context, None);
|
|
|
|
|
|
|
|
{
|
|
|
|
// The node should be cloned.
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_NE(D, MapMetadata(D, VM, RF_None));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// The node should be moved.
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ValueMapperTest, MapMetadataDistinctOperands) {
|
|
|
|
LLVMContext Context;
|
|
|
|
Metadata *Old = MDTuple::getDistinct(Context, None);
|
|
|
|
auto *D = MDTuple::getDistinct(Context, Old);
|
|
|
|
ASSERT_EQ(Old, D->getOperand(0));
|
|
|
|
|
|
|
|
Metadata *New = MDTuple::getDistinct(Context, None);
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
VM.MD()[Old].reset(New);
|
|
|
|
|
|
|
|
// Make sure operands are updated.
|
|
|
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
|
|
|
|
EXPECT_EQ(New, D->getOperand(0));
|
|
|
|
}
|
|
|
|
|
2016-04-03 01:04:38 +08:00
|
|
|
TEST(ValueMapperTest, MapMetadataSeeded) {
|
|
|
|
LLVMContext Context;
|
|
|
|
auto *D = MDTuple::getDistinct(Context, None);
|
|
|
|
|
|
|
|
// The node should be moved.
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(None, VM.getMappedMD(D));
|
|
|
|
|
|
|
|
VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
|
|
|
|
EXPECT_EQ(D, *VM.getMappedMD(D));
|
|
|
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_None));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ValueMapperTest, MapMetadataSeededWithNull) {
|
|
|
|
LLVMContext Context;
|
|
|
|
auto *D = MDTuple::getDistinct(Context, None);
|
|
|
|
|
|
|
|
// The node should be moved.
|
|
|
|
ValueToValueMapTy VM;
|
|
|
|
EXPECT_EQ(None, VM.getMappedMD(D));
|
|
|
|
|
|
|
|
VM.MD().insert(std::make_pair(D, TrackingMDRef()));
|
|
|
|
EXPECT_EQ(nullptr, *VM.getMappedMD(D));
|
|
|
|
EXPECT_EQ(nullptr, MapMetadata(D, VM, RF_None));
|
|
|
|
}
|
|
|
|
|
2016-04-03 00:45:51 +08:00
|
|
|
} // end namespace
|