diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /unittests/IR | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'unittests/IR')
-rw-r--r-- | unittests/IR/CMakeLists.txt | 17 | ||||
-rw-r--r-- | unittests/IR/ConstantRangeTest.cpp | 512 | ||||
-rw-r--r-- | unittests/IR/ConstantsTest.cpp | 2 | ||||
-rw-r--r-- | unittests/IR/DominatorTreeTest.cpp | 40 | ||||
-rw-r--r-- | unittests/IR/IRBuilderTest.cpp | 69 | ||||
-rw-r--r-- | unittests/IR/InstructionsTest.cpp | 79 | ||||
-rw-r--r-- | unittests/IR/LeakDetectorTest.cpp | 31 | ||||
-rw-r--r-- | unittests/IR/LegacyPassManagerTest.cpp | 30 | ||||
-rw-r--r-- | unittests/IR/MetadataTest.cpp | 2 | ||||
-rw-r--r-- | unittests/IR/PassManagerTest.cpp | 275 | ||||
-rw-r--r-- | unittests/IR/PatternMatch.cpp | 373 | ||||
-rw-r--r-- | unittests/IR/ValueHandleTest.cpp | 407 | ||||
-rw-r--r-- | unittests/IR/ValueMapTest.cpp | 10 | ||||
-rw-r--r-- | unittests/IR/ValueTest.cpp | 4 | ||||
-rw-r--r-- | unittests/IR/VerifierTest.cpp | 18 |
15 files changed, 1615 insertions, 254 deletions
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index fd0831f..7368a24 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -1,15 +1,19 @@ set(LLVM_LINK_COMPONENTS - asmparser - core - ipa + Analysis + AsmParser + Core + IPA + Support ) set(IRSources AttributesTest.cpp + ConstantRangeTest.cpp ConstantsTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp + LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp @@ -17,18 +21,13 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp VerifierTest.cpp WaymarkTest.cpp ) -# MSVC9 and 8 cannot compile ValueMapTest.cpp due to their bug. -# See issue#331418 in Visual Studio. -if(MSVC AND MSVC_VERSION LESS 1600) - list(REMOVE_ITEM IRSources ValueMapTest.cpp) -endif() - # HACK: Declare a couple of source files as optionally compiled to satisfy the # missing-file-checker in LLVM's weird CMake build. set(LLVM_OPTIONAL_SOURCES diff --git a/unittests/IR/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp new file mode 100644 index 0000000..cdf7378 --- /dev/null +++ b/unittests/IR/ConstantRangeTest.cpp @@ -0,0 +1,512 @@ +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Instructions.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class ConstantRangeTest : public ::testing::Test { +protected: + static ConstantRange Full; + static ConstantRange Empty; + static ConstantRange One; + static ConstantRange Some; + static ConstantRange Wrap; +}; + +ConstantRange ConstantRangeTest::Full(16); +ConstantRange ConstantRangeTest::Empty(16, false); +ConstantRange ConstantRangeTest::One(APInt(16, 0xa)); +ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa)); +ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa)); + +TEST_F(ConstantRangeTest, Basics) { + EXPECT_TRUE(Full.isFullSet()); + EXPECT_FALSE(Full.isEmptySet()); + EXPECT_TRUE(Full.inverse().isEmptySet()); + EXPECT_FALSE(Full.isWrappedSet()); + EXPECT_TRUE(Full.contains(APInt(16, 0x0))); + EXPECT_TRUE(Full.contains(APInt(16, 0x9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xa))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Empty.isFullSet()); + EXPECT_TRUE(Empty.isEmptySet()); + EXPECT_TRUE(Empty.inverse().isFullSet()); + EXPECT_FALSE(Empty.isWrappedSet()); + EXPECT_FALSE(Empty.contains(APInt(16, 0x0))); + EXPECT_FALSE(Empty.contains(APInt(16, 0x9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xa))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(One.isFullSet()); + EXPECT_FALSE(One.isEmptySet()); + EXPECT_FALSE(One.isWrappedSet()); + EXPECT_FALSE(One.contains(APInt(16, 0x0))); + EXPECT_FALSE(One.contains(APInt(16, 0x9))); + EXPECT_TRUE(One.contains(APInt(16, 0xa))); + EXPECT_FALSE(One.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(One.contains(APInt(16, 0xaaa))); + EXPECT_FALSE(One.inverse().contains(APInt(16, 0xa))); + + EXPECT_FALSE(Some.isFullSet()); + EXPECT_FALSE(Some.isEmptySet()); + EXPECT_FALSE(Some.isWrappedSet()); + EXPECT_FALSE(Some.contains(APInt(16, 0x0))); + EXPECT_FALSE(Some.contains(APInt(16, 0x9))); + EXPECT_TRUE(Some.contains(APInt(16, 0xa))); + EXPECT_TRUE(Some.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Some.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Wrap.isFullSet()); + EXPECT_FALSE(Wrap.isEmptySet()); + EXPECT_TRUE(Wrap.isWrappedSet()); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x0))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x9))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xa))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa))); +} + +TEST_F(ConstantRangeTest, Equality) { + EXPECT_EQ(Full, Full); + EXPECT_EQ(Empty, Empty); + EXPECT_EQ(One, One); + EXPECT_EQ(Some, Some); + EXPECT_EQ(Wrap, Wrap); + EXPECT_NE(Full, Empty); + EXPECT_NE(Full, One); + EXPECT_NE(Full, Some); + EXPECT_NE(Full, Wrap); + EXPECT_NE(Empty, One); + EXPECT_NE(Empty, Some); + EXPECT_NE(Empty, Wrap); + EXPECT_NE(One, Some); + EXPECT_NE(One, Wrap); + EXPECT_NE(Some, Wrap); +} + +TEST_F(ConstantRangeTest, SingleElement) { + EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL)); + + EXPECT_FALSE(Full.isSingleElement()); + EXPECT_FALSE(Empty.isSingleElement()); + EXPECT_TRUE(One.isSingleElement()); + EXPECT_FALSE(Some.isSingleElement()); + EXPECT_FALSE(Wrap.isSingleElement()); +} + +TEST_F(ConstantRangeTest, GetSetSize) { + EXPECT_EQ(Full.getSetSize(), APInt(17, 65536)); + EXPECT_EQ(Empty.getSetSize(), APInt(17, 0)); + EXPECT_EQ(One.getSetSize(), APInt(17, 1)); + EXPECT_EQ(Some.getSetSize(), APInt(17, 0xaa0)); + + ConstantRange Wrap(APInt(4, 7), APInt(4, 3)); + ConstantRange Wrap2(APInt(4, 8), APInt(4, 7)); + EXPECT_EQ(Wrap.getSetSize(), APInt(5, 12)); + EXPECT_EQ(Wrap2.getSetSize(), APInt(5, 15)); +} + +TEST_F(ConstantRangeTest, GetMinsAndMaxes) { + EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX)); + EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX)); + + EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0)); + EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0)); + + EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX)); + EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX)); + + EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + + // Found by Klee + EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(), + APInt(4, 7)); +} + +TEST_F(ConstantRangeTest, SignWrapped) { + EXPECT_TRUE(Full.isSignWrappedSet()); + EXPECT_FALSE(Empty.isSignWrappedSet()); + EXPECT_FALSE(One.isSignWrappedSet()); + EXPECT_FALSE(Some.isSignWrappedSet()); + EXPECT_TRUE(Wrap.isSignWrappedSet()); + + EXPECT_FALSE(ConstantRange(APInt(8, 127), APInt(8, 128)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 127), APInt(8, 129)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 128), APInt(8, 129)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 9)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 250)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 10)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 251)).isSignWrappedSet()); +} + +TEST_F(ConstantRangeTest, Trunc) { + ConstantRange TFull = Full.truncate(10); + ConstantRange TEmpty = Empty.truncate(10); + ConstantRange TOne = One.truncate(10); + ConstantRange TSome = Some.truncate(10); + ConstantRange TWrap = Wrap.truncate(10); + EXPECT_TRUE(TFull.isFullSet()); + EXPECT_TRUE(TEmpty.isEmptySet()); + EXPECT_EQ(TOne, ConstantRange(One.getLower().trunc(10), + One.getUpper().trunc(10))); + EXPECT_TRUE(TSome.isFullSet()); +} + +TEST_F(ConstantRangeTest, ZExt) { + ConstantRange ZFull = Full.zeroExtend(20); + ConstantRange ZEmpty = Empty.zeroExtend(20); + ConstantRange ZOne = One.zeroExtend(20); + ConstantRange ZSome = Some.zeroExtend(20); + ConstantRange ZWrap = Wrap.zeroExtend(20); + EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + EXPECT_TRUE(ZEmpty.isEmptySet()); + EXPECT_EQ(ZOne, ConstantRange(One.getLower().zext(20), + One.getUpper().zext(20))); + EXPECT_EQ(ZSome, ConstantRange(Some.getLower().zext(20), + Some.getUpper().zext(20))); + EXPECT_EQ(ZWrap, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + + // zext([5, 0), 3->7) = [5, 8) + ConstantRange FiveZero(APInt(3, 5), APInt(3, 0)); + EXPECT_EQ(FiveZero.zeroExtend(7), ConstantRange(APInt(7, 5), APInt(7, 8))); +} + +TEST_F(ConstantRangeTest, SExt) { + ConstantRange SFull = Full.signExtend(20); + ConstantRange SEmpty = Empty.signExtend(20); + ConstantRange SOne = One.signExtend(20); + ConstantRange SSome = Some.signExtend(20); + ConstantRange SWrap = Wrap.signExtend(20); + EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + EXPECT_TRUE(SEmpty.isEmptySet()); + EXPECT_EQ(SOne, ConstantRange(One.getLower().sext(20), + One.getUpper().sext(20))); + EXPECT_EQ(SSome, ConstantRange(Some.getLower().sext(20), + Some.getUpper().sext(20))); + EXPECT_EQ(SWrap, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + + EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16), + ConstantRange(APInt(16, -128), APInt(16, 128))); + + EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19), + ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000))); +} + +TEST_F(ConstantRangeTest, IntersectWith) { + EXPECT_EQ(Empty.intersectWith(Full), Empty); + EXPECT_EQ(Empty.intersectWith(Empty), Empty); + EXPECT_EQ(Empty.intersectWith(One), Empty); + EXPECT_EQ(Empty.intersectWith(Some), Empty); + EXPECT_EQ(Empty.intersectWith(Wrap), Empty); + EXPECT_EQ(Full.intersectWith(Full), Full); + EXPECT_EQ(Some.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One)); + + // Klee generated testcase from PR4545. + // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like + // 01..4.6789ABCDEF where the dots represent values not in the intersection. + ConstantRange LHS(APInt(16, 4), APInt(16, 2)); + ConstantRange RHS(APInt(16, 6), APInt(16, 5)); + EXPECT_TRUE(LHS.intersectWith(RHS) == LHS); + + // previous bug: intersection of [min, 3) and [2, max) should be 2 + LHS = ConstantRange(APInt(32, -2147483646), APInt(32, 3)); + RHS = ConstantRange(APInt(32, 2), APInt(32, 2147483646)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2))); + + // [2, 0) /\ [4, 3) = [2, 0) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 4), APInt(32, 3)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2), APInt(32, 0))); + + // [2, 0) /\ [4, 2) = [4, 0) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 0))); + + // [4, 2) /\ [5, 1) = [5, 1) + LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + RHS = ConstantRange(APInt(32, 5), APInt(32, 1)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 5), APInt(32, 1))); + + // [2, 0) /\ [7, 4) = [7, 4) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 7), APInt(32, 4)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 7), APInt(32, 4))); + + // [4, 2) /\ [1, 0) = [1, 0) + LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + RHS = ConstantRange(APInt(32, 1), APInt(32, 0)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 2))); + + // [15, 0) /\ [7, 6) = [15, 0) + LHS = ConstantRange(APInt(32, 15), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 7), APInt(32, 6)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0))); +} + +TEST_F(ConstantRangeTest, UnionWith) { + EXPECT_EQ(Wrap.unionWith(One), + ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb))); + EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One)); + EXPECT_EQ(Empty.unionWith(Empty), Empty); + EXPECT_EQ(Full.unionWith(Full), Full); + EXPECT_EQ(Some.unionWith(Wrap), Full); + + // PR4545 + EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith( + ConstantRange(APInt(16, 0), APInt(16, 8))), + ConstantRange(APInt(16, 14), APInt(16, 8))); + EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith( + ConstantRange(APInt(16, 4), APInt(16, 0))), + ConstantRange(16)); + EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith( + ConstantRange(APInt(16, 2), APInt(16, 1))), + ConstantRange(16)); +} + +TEST_F(ConstantRangeTest, SetDifference) { + EXPECT_EQ(Full.difference(Empty), Full); + EXPECT_EQ(Full.difference(Full), Empty); + EXPECT_EQ(Empty.difference(Empty), Empty); + EXPECT_EQ(Empty.difference(Full), Empty); + + ConstantRange A(APInt(16, 3), APInt(16, 7)); + ConstantRange B(APInt(16, 5), APInt(16, 9)); + ConstantRange C(APInt(16, 3), APInt(16, 5)); + ConstantRange D(APInt(16, 7), APInt(16, 9)); + ConstantRange E(APInt(16, 5), APInt(16, 4)); + ConstantRange F(APInt(16, 7), APInt(16, 3)); + EXPECT_EQ(A.difference(B), C); + EXPECT_EQ(B.difference(A), D); + EXPECT_EQ(E.difference(A), F); +} + +TEST_F(ConstantRangeTest, SubtractAPInt) { + EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); + EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty); + EXPECT_EQ(Some.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Wrap.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Add) { + EXPECT_EQ(Full.add(APInt(16, 4)), Full); + EXPECT_EQ(Full.add(Full), Full); + EXPECT_EQ(Full.add(Empty), Empty); + EXPECT_EQ(Full.add(One), Full); + EXPECT_EQ(Full.add(Some), Full); + EXPECT_EQ(Full.add(Wrap), Full); + EXPECT_EQ(Empty.add(Empty), Empty); + EXPECT_EQ(Empty.add(One), Empty); + EXPECT_EQ(Empty.add(Some), Empty); + EXPECT_EQ(Empty.add(Wrap), Empty); + EXPECT_EQ(Empty.add(APInt(16, 4)), Empty); + EXPECT_EQ(Some.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe), APInt(16, 0xaae))); + EXPECT_EQ(Wrap.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xaae), APInt(16, 0xe))); + EXPECT_EQ(One.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe))); +} + +TEST_F(ConstantRangeTest, Sub) { + EXPECT_EQ(Full.sub(APInt(16, 4)), Full); + EXPECT_EQ(Full.sub(Full), Full); + EXPECT_EQ(Full.sub(Empty), Empty); + EXPECT_EQ(Full.sub(One), Full); + EXPECT_EQ(Full.sub(Some), Full); + EXPECT_EQ(Full.sub(Wrap), Full); + EXPECT_EQ(Empty.sub(Empty), Empty); + EXPECT_EQ(Empty.sub(One), Empty); + EXPECT_EQ(Empty.sub(Some), Empty); + EXPECT_EQ(Empty.sub(Wrap), Empty); + EXPECT_EQ(Empty.sub(APInt(16, 4)), Empty); + EXPECT_EQ(Some.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Some.sub(Some), + ConstantRange(APInt(16, 0xf561), APInt(16, 0xaa0))); + EXPECT_EQ(Wrap.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Multiply) { + EXPECT_EQ(Full.multiply(Full), Full); + EXPECT_EQ(Full.multiply(Empty), Empty); + EXPECT_EQ(Full.multiply(One), Full); + EXPECT_EQ(Full.multiply(Some), Full); + EXPECT_EQ(Full.multiply(Wrap), Full); + EXPECT_EQ(Empty.multiply(Empty), Empty); + EXPECT_EQ(Empty.multiply(One), Empty); + EXPECT_EQ(Empty.multiply(Some), Empty); + EXPECT_EQ(Empty.multiply(Wrap), Empty); + EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xa + 1))); + EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xaa9 + 1))); + EXPECT_EQ(One.multiply(Wrap), Full); + EXPECT_EQ(Some.multiply(Some), Full); + EXPECT_EQ(Some.multiply(Wrap), Full); + EXPECT_EQ(Wrap.multiply(Wrap), Full); + + ConstantRange Zero(APInt(16, 0)); + EXPECT_EQ(Zero.multiply(Full), Zero); + EXPECT_EQ(Zero.multiply(Some), Zero); + EXPECT_EQ(Zero.multiply(Wrap), Zero); + EXPECT_EQ(Full.multiply(Zero), Zero); + EXPECT_EQ(Some.multiply(Zero), Zero); + EXPECT_EQ(Wrap.multiply(Zero), Zero); + + // http://llvm.org/PR4545 + EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply( + ConstantRange(APInt(4, 6), APInt(4, 2))), + ConstantRange(4, /*isFullSet=*/true)); +} + +TEST_F(ConstantRangeTest, UMax) { + EXPECT_EQ(Full.umax(Full), Full); + EXPECT_EQ(Full.umax(Empty), Empty); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Full.umax(Wrap), Full); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Empty.umax(Empty), Empty); + EXPECT_EQ(Empty.umax(Some), Empty); + EXPECT_EQ(Empty.umax(Wrap), Empty); + EXPECT_EQ(Empty.umax(One), Empty); + EXPECT_EQ(Some.umax(Some), Some); + EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Some.umax(One), Some); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.umax(Wrap), Full); + EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(One.umax(One), One); +} + +TEST_F(ConstantRangeTest, SMax) { + EXPECT_EQ(Full.smax(Full), Full); + EXPECT_EQ(Full.smax(Empty), Empty); + EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Full.smax(Wrap), Full); + EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Empty.smax(Empty), Empty); + EXPECT_EQ(Empty.smax(Some), Empty); + EXPECT_EQ(Empty.smax(Wrap), Empty); + EXPECT_EQ(Empty.smax(One), Empty); + EXPECT_EQ(Some.smax(Some), Some); + EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(Some.smax(One), Some); + EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(One.smax(One), One); +} + +TEST_F(ConstantRangeTest, UDiv) { + EXPECT_EQ(Full.udiv(Full), Full); + EXPECT_EQ(Full.udiv(Empty), Empty); + EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Wrap), Full); + EXPECT_EQ(Empty.udiv(Empty), Empty); + EXPECT_EQ(Empty.udiv(One), Empty); + EXPECT_EQ(Empty.udiv(Some), Empty); + EXPECT_EQ(Empty.udiv(Wrap), Empty); + EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1))); + EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2))); + EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111))); + EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.udiv(Wrap), Full); +} + +TEST_F(ConstantRangeTest, Shl) { + EXPECT_EQ(Full.shl(Full), Full); + EXPECT_EQ(Full.shl(Empty), Empty); + EXPECT_EQ(Full.shl(One), Full); // TODO: [0, (-1 << 0xa) + 1) + EXPECT_EQ(Full.shl(Some), Full); // TODO: [0, (-1 << 0xa) + 1) + EXPECT_EQ(Full.shl(Wrap), Full); + EXPECT_EQ(Empty.shl(Empty), Empty); + EXPECT_EQ(Empty.shl(One), Empty); + EXPECT_EQ(Empty.shl(Some), Empty); + EXPECT_EQ(Empty.shl(Wrap), Empty); + EXPECT_EQ(One.shl(One), ConstantRange(APInt(16, 0xa << 0xa), + APInt(16, (0xa << 0xa) + 1))); + EXPECT_EQ(One.shl(Some), Full); // TODO: [0xa << 0xa, 0) + EXPECT_EQ(One.shl(Wrap), Full); // TODO: [0xa, 0xa << 14 + 1) + EXPECT_EQ(Some.shl(Some), Full); // TODO: [0xa << 0xa, 0xfc01) + EXPECT_EQ(Some.shl(Wrap), Full); // TODO: [0xa, 0x7ff << 0x5 + 1) + EXPECT_EQ(Wrap.shl(Wrap), Full); +} + +TEST_F(ConstantRangeTest, Lshr) { + EXPECT_EQ(Full.lshr(Full), Full); + EXPECT_EQ(Full.lshr(Empty), Empty); + EXPECT_EQ(Full.lshr(One), ConstantRange(APInt(16, 0), + APInt(16, (0xffff >> 0xa) + 1))); + EXPECT_EQ(Full.lshr(Some), ConstantRange(APInt(16, 0), + APInt(16, (0xffff >> 0xa) + 1))); + EXPECT_EQ(Full.lshr(Wrap), Full); + EXPECT_EQ(Empty.lshr(Empty), Empty); + EXPECT_EQ(Empty.lshr(One), Empty); + EXPECT_EQ(Empty.lshr(Some), Empty); + EXPECT_EQ(Empty.lshr(Wrap), Empty); + EXPECT_EQ(One.lshr(One), ConstantRange(APInt(16, 0))); + EXPECT_EQ(One.lshr(Some), ConstantRange(APInt(16, 0))); + EXPECT_EQ(One.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.lshr(Some), ConstantRange(APInt(16, 0), + APInt(16, (0xaaa >> 0xa) + 1))); + EXPECT_EQ(Some.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.lshr(Wrap), Full); +} + +TEST(ConstantRange, MakeICmpRegion) { + // PR8250 + ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32)); + EXPECT_TRUE(ConstantRange::makeICmpRegion(ICmpInst::ICMP_SGT, + SMax).isEmptySet()); +} + +} // anonymous namespace diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index fee38b8..b3aa810 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -162,7 +162,7 @@ TEST(ConstantsTest, PointerCast) { } TEST(ConstantsTest, AsInstructionsTest) { - OwningPtr<Module> M(new Module("MyModule", getGlobalContext())); + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); Type *Int64Ty = Type::getInt64Ty(getGlobalContext()); Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index 4e5af93..98c2317 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Dominators.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -25,7 +26,9 @@ namespace llvm { struct DPass : public FunctionPass { static char ID; virtual bool runOnFunction(Function &F) { - DominatorTree *DT = &getAnalysis<DominatorTree>(); + DominatorTree *DT = + &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + PostDominatorTree *PDT = &getAnalysis<PostDominatorTree>(); Function::iterator FI = F.begin(); BasicBlock *BB0 = FI++; @@ -148,10 +151,34 @@ namespace llvm { EXPECT_TRUE(DT->dominates(Y6, BB3)); + // Post dominance. + EXPECT_TRUE(PDT->dominates(BB0, BB0)); + EXPECT_FALSE(PDT->dominates(BB1, BB0)); + EXPECT_FALSE(PDT->dominates(BB2, BB0)); + EXPECT_FALSE(PDT->dominates(BB3, BB0)); + EXPECT_TRUE(PDT->dominates(BB4, BB1)); + + // Dominance descendants. + SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs; + + DT->getDescendants(BB0, DominatedBBs); + PDT->getDescendants(BB0, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 4UL); + EXPECT_EQ(PostDominatedBBs.size(), 1UL); + + // BB3 is unreachable. It should have no dominators nor postdominators. + DominatedBBs.clear(); + PostDominatedBBs.clear(); + DT->getDescendants(BB3, DominatedBBs); + DT->getDescendants(BB3, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 0UL); + EXPECT_EQ(PostDominatedBBs.size(), 0UL); + return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); + AU.addRequired<PostDominatorTree>(); } DPass() : FunctionPass(ID) { initializeDPassPass(*PassRegistry::getPassRegistry()); @@ -191,7 +218,7 @@ namespace llvm { TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - OwningPtr<Module> M(makeLLVMModule(P)); + std::unique_ptr<Module> M(makeLLVMModule(P)); PassManager Passes; Passes.add(P); Passes.run(*M); @@ -200,5 +227,6 @@ namespace llvm { } INITIALIZE_PASS_BEGIN(DPass, "dpass", "dpass", false, false) -INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_END(DPass, "dpass", "dpass", false, false) diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2f390f7..9796e44 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/IRBuilder.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" @@ -16,6 +15,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "gtest/gtest.h" using namespace llvm; @@ -40,7 +40,7 @@ protected: } LLVMContext Ctx; - OwningPtr<Module> M; + std::unique_ptr<Module> M; Function *F; BasicBlock *BB; GlobalVariable *GV; @@ -107,6 +107,14 @@ TEST_F(IRBuilderTest, LandingPadName) { EXPECT_EQ(LP->getName(), "LP"); } +TEST_F(IRBuilderTest, DataLayout) { + std::unique_ptr<Module> M(new Module("test", Ctx)); + M->setDataLayout("e-n32"); + EXPECT_TRUE(M->getDataLayout()->isLegalInteger(32)); + M->setDataLayout("e"); + EXPECT_FALSE(M->getDataLayout()->isLegalInteger(32)); +} + TEST_F(IRBuilderTest, GetIntTy) { IRBuilder<> Builder(BB); IntegerType *Ty1 = Builder.getInt1Ty(); @@ -147,6 +155,13 @@ TEST_F(IRBuilderTest, FastMathFlags) { FAdd = cast<Instruction>(F); EXPECT_TRUE(FAdd->hasNoNaNs()); + // Now, try it with CreateBinOp + F = Builder.CreateBinOp(Instruction::FAdd, F, F); + EXPECT_TRUE(Builder.getFastMathFlags().any()); + ASSERT_TRUE(isa<Instruction>(F)); + FAdd = cast<Instruction>(F); + EXPECT_TRUE(FAdd->hasNoNaNs()); + F = Builder.CreateFDiv(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); EXPECT_TRUE(Builder.getFastMathFlags().UnsafeAlgebra); @@ -183,6 +198,56 @@ TEST_F(IRBuilderTest, FastMathFlags) { } +TEST_F(IRBuilderTest, WrapFlags) { + IRBuilder<true, NoFolder> Builder(BB); + + // Test instructions. + GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true, + GlobalValue::ExternalLinkage, 0); + Value *V = Builder.CreateLoad(G); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); + + // Test operators created with constants. + Constant *C = Builder.getInt32(42); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); +} + TEST_F(IRBuilderTest, RAIIHelpersTest) { IRBuilder<> Builder(BB); EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal()); diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 65f85ba..e76afa8 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -14,11 +14,14 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" +#include <memory> namespace llvm { namespace { @@ -47,6 +50,58 @@ TEST(InstructionsTest, ReturnInst) { delete r1; } +// Test fixture that provides a module and a single function within it. Useful +// for tests that need to refer to the function in some way. +class ModuleWithFunctionTest : public testing::Test { +protected: + ModuleWithFunctionTest() : M(new Module("MyModule", Ctx)) { + FArgTypes.push_back(Type::getInt8Ty(Ctx)); + FArgTypes.push_back(Type::getInt32Ty(Ctx)); + FArgTypes.push_back(Type::getInt64Ty(Ctx)); + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Ctx), FArgTypes, false); + F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); + } + + LLVMContext Ctx; + std::unique_ptr<Module> M; + SmallVector<Type *, 3> FArgTypes; + Function *F; +}; + +TEST_F(ModuleWithFunctionTest, CallInst) { + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<CallInst> Call(CallInst::Create(F, Args)); + + // Make sure iteration over a call's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Call->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Call->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + +TEST_F(ModuleWithFunctionTest, InvokeInst) { + BasicBlock *BB1 = BasicBlock::Create(Ctx, "", F); + BasicBlock *BB2 = BasicBlock::Create(Ctx, "", F); + + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<InvokeInst> Invoke(InvokeInst::Create(F, BB1, BB2, Args)); + + // Make sure iteration over invoke's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Invoke->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Invoke->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + TEST(InstructionsTest, BranchInst) { LLVMContext &C(getGlobalContext()); @@ -65,9 +120,9 @@ TEST(InstructionsTest, BranchInst) { EXPECT_EQ(1U, b0->getNumOperands()); EXPECT_NE(b0->op_begin(), b0->op_end()); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); IntegerType* Int1 = IntegerType::get(C, 1); Constant* One = ConstantInt::get(Int1, 1, true); @@ -145,6 +200,7 @@ TEST(InstructionsTest, CastInst) { Type *V2Int64PtrTy = VectorType::get(Int64PtrTy, 2); Type *V2Int32PtrTy = VectorType::get(Int32PtrTy, 2); + Type *V4Int32PtrTy = VectorType::get(Int32PtrTy, 4); const Constant* c8 = Constant::getNullValue(V8x8Ty); const Constant* c64 = Constant::getNullValue(V8x64Ty); @@ -205,6 +261,21 @@ TEST(InstructionsTest, CastInst) { EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V4Int32PtrTy), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrTy)); + + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V4Int32PtrAS1Ty), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrAS1Ty)); + + // Check that assertion is not hit when creating a cast with a vector of // pointers // First form @@ -269,7 +340,7 @@ TEST(InstructionsTest, VectorGep) { int64_t Offset; DataLayout TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3" - "2:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80" + "2:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-s:64:64-f80" ":128:128-n8:16:32:64-S128"); // Make sure we don't crash GetPointerBaseWithConstantOffset(Gep0, Offset, &TD); @@ -381,7 +452,7 @@ TEST(InstructionsTest, isEliminableCastPair) { // or if we don't have available pointer size information. DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16" "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64" - "-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"); + "-v128:128:128-a:0:64-s:64:64-f80:128:128-n8:16:32:64-S128"); Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1); Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2); diff --git a/unittests/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp new file mode 100644 index 0000000..94eed4c --- /dev/null +++ b/unittests/IR/LeakDetectorTest.cpp @@ -0,0 +1,31 @@ +//===- LeakDetectorTest.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/LeakDetector.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(LeakDetector, Death1) { + LeakDetector::addGarbageObject((void*) 1); + LeakDetector::addGarbageObject((void*) 2); + + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), + ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), + "Cache != o && \"Object already in set!\""); +} +#endif +#endif + +} diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 11841bd..df6f460 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -19,8 +19,6 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/PrintModulePass.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" @@ -28,10 +26,12 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -99,7 +99,7 @@ namespace llvm { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run++; return false; } @@ -176,7 +176,7 @@ namespace llvm { initializeCGPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnSCC(CallGraphSCC &SCMM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -215,7 +215,7 @@ namespace llvm { return false; } virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -252,7 +252,7 @@ namespace llvm { return false; } virtual bool runOnBasicBlock(BasicBlock &BB) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -277,7 +277,7 @@ namespace llvm { initializeFPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; { @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); Passes.add(mNDM2); Passes.add(mNDM); Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -346,10 +346,10 @@ namespace llvm { template<typename T> void MemoryTestHelper(int run) { - OwningPtr<Module> M(makeLLVMModule()); + std::unique_ptr<Module> M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayout(M.get())); + Passes.add(new DataLayoutPass(M.get())); Passes.add(P); Passes.run(*M); T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm { Module *M = makeLLVMModule(); T *P = new T(); PassManager Passes; - Passes.add(new DataLayout(M)); + Passes.add(new DataLayoutPass(M)); Passes.add(P); Passes.run(*M); T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); PassManager Passes; - Passes.add(new DataLayout(M)); + Passes.add(new DataLayoutPass(M)); Passes.add(O); Passes.run(*M); @@ -412,7 +412,7 @@ namespace llvm { Module* mod = new Module("test-mem", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" - "a0:0:64-s0:64:64-f80:128:128"); + "a:0:64-s:64:64-f80:128:128"); mod->setTargetTriple("x86_64-unknown-linux-gnu"); // Type Definitions @@ -550,7 +550,7 @@ namespace llvm { INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) -INITIALIZE_PASS_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS(FPass, "fp","fp", false, false) INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 352e83e..00a2783 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 7b60e38..310e48f 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -19,21 +19,21 @@ using namespace llvm; namespace { -class TestAnalysisPass { +class TestFunctionAnalysis { public: - typedef Function IRUnitT; - struct Result { Result(int Count) : InstructionCount(Count) {} - bool invalidate(Function *) { return true; } int InstructionCount; }; /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} + /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F) { + Result run(Function *F, FunctionAnalysisManager *AM) { + ++Runs; int Count = 0; for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; @@ -45,38 +45,124 @@ public: private: /// \brief Private static data to provide unique ID. static char PassID; + + int &Runs; }; -char TestAnalysisPass::PassID; +char TestFunctionAnalysis::PassID; + +class TestModuleAnalysis { +public: + struct Result { + Result(int Count) : FunctionCount(Count) {} + int FunctionCount; + }; + + static void *ID() { return (void *)&PassID; } + + TestModuleAnalysis(int &Runs) : Runs(Runs) {} + + Result run(Module *M, ModuleAnalysisManager *AM) { + ++Runs; + int Count = 0; + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + ++Count; + return Result(Count); + } + +private: + static char PassID; + + int &Runs; +}; + +char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - bool run(Module *M) { + PreservedAnalyses run(Module *M) { ++RunCount; - return true; + return PreservedAnalyses::none(); } + static StringRef name() { return "TestModulePass"; } + int &RunCount; }; -struct TestFunctionPass { - TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount) - : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) { +struct TestPreservingModulePass { + PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + + static StringRef name() { return "TestPreservingModulePass"; } +}; + +struct TestMinPreservingModulePass { + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses PA; + + // Force running an analysis. + (void)AM->getResult<TestModuleAnalysis>(M); + + PA.preserve<FunctionAnalysisManagerModuleProxy>(); + return PA; } - bool run(Function *F) { + static StringRef name() { return "TestMinPreservingModulePass"; } +}; + +struct TestFunctionPass { + TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, + int &AnalyzedFunctionCount, + bool OnlyUseCachedResults = false) + : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), + AnalyzedFunctionCount(AnalyzedFunctionCount), + OnlyUseCachedResults(OnlyUseCachedResults) {} + + PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { ++RunCount; - const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F); - AnalyzedInstrCount += AR.InstructionCount; + const ModuleAnalysisManager &MAM = + AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + if (TestModuleAnalysis::Result *TMA = + MAM.getCachedResult<TestModuleAnalysis>(F->getParent())) + AnalyzedFunctionCount += TMA->FunctionCount; - return true; + if (OnlyUseCachedResults) { + // Hack to force the use of the cached interface. + if (TestFunctionAnalysis::Result *AR = + AM->getCachedResult<TestFunctionAnalysis>(F)) + AnalyzedInstrCount += AR->InstructionCount; + } else { + // Typical path just runs the analysis as needed. + TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F); + AnalyzedInstrCount += AR.InstructionCount; + } + + return PreservedAnalyses::all(); } - AnalysisManager &AM; + static StringRef name() { return "TestFunctionPass"; } + int &RunCount; int &AnalyzedInstrCount; + int &AnalyzedFunctionCount; + bool OnlyUseCachedResults; +}; + +// A test function pass that invalidates all function analyses for a function +// with a specific name. +struct TestInvalidationFunctionPass { + TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} + + PreservedAnalyses run(Function *F) { + return F->getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + } + + static StringRef name() { return "TestInvalidationFunctionPass"; } + + StringRef Name; }; Module *parseIR(const char *IR) { @@ -87,7 +173,7 @@ Module *parseIR(const char *IR) { class PassManagerTest : public ::testing::Test { protected: - OwningPtr<Module> M; + std::unique_ptr<Module> M; public: PassManagerTest() @@ -105,27 +191,154 @@ public: "}\n")) {} }; +TEST_F(PassManagerTest, BasicPreservedAnalyses) { + PreservedAnalyses PA1 = PreservedAnalyses(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA2 = PreservedAnalyses::none(); + EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA3 = PreservedAnalyses::all(); + EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA4 = PA1; + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4 = PA3; + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>()); + PA4 = std::move(PA2); + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA1.preserve<TestModuleAnalysis>(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.intersect(PA4); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); +} + TEST_F(PassManagerTest, Basic) { - AnalysisManager AM(M.get()); - AM.registerAnalysisPass(TestAnalysisPass()); + FunctionAnalysisManager FAM; + int FunctionAnalysisRuns = 0; + FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns)); - ModulePassManager MPM(M.get(), &AM); - FunctionPassManager FPM(&AM); + ModuleAnalysisManager MAM; + int ModuleAnalysisRuns = 0; + MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns)); + MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); + FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); + + ModulePassManager MPM; + + // Count the runs over a Function. + int FunctionPassRunCount1 = 0; + int AnalyzedInstrCount1 = 0; + int AnalyzedFunctionCount1 = 0; + { + // Pointless scoped copy to test move assignment. + ModulePassManager NestedMPM; + FunctionPassManager FPM; + { + // Pointless scope to test move assignment. + FunctionPassManager NestedFPM; + NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1, + AnalyzedFunctionCount1)); + FPM = std::move(NestedFPM); + } + NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + MPM = std::move(NestedMPM); + } // Count the runs over a module. int ModulePassRunCount = 0; MPM.addPass(TestModulePass(ModulePassRunCount)); - // Count the runs over a Function. - int FunctionPassRunCount = 0; - int AnalyzedInstrCount = 0; - FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount)); - MPM.addPass(FPM); + // Count the runs over a Function in a separate manager. + int FunctionPassRunCount2 = 0; + int AnalyzedInstrCount2 = 0; + int AnalyzedFunctionCount2 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, + AnalyzedFunctionCount2)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A third function pass manager but with only preserving intervening passes + // and with a function pass that invalidates exactly one analysis. + MPM.addPass(TestPreservingModulePass()); + int FunctionPassRunCount3 = 0; + int AnalyzedInstrCount3 = 0; + int AnalyzedFunctionCount3 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, + AnalyzedFunctionCount3)); + FPM.addPass(TestInvalidationFunctionPass("f")); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A fourth function pass manager but with a minimal intervening passes. + MPM.addPass(TestMinPreservingModulePass()); + int FunctionPassRunCount4 = 0; + int AnalyzedInstrCount4 = 0; + int AnalyzedFunctionCount4 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, + AnalyzedFunctionCount4)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } - MPM.run(); + // A fifth function pass manager but which uses only cached results. + int FunctionPassRunCount5 = 0; + int AnalyzedInstrCount5 = 0; + int AnalyzedFunctionCount5 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestInvalidationFunctionPass("f")); + FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, + AnalyzedFunctionCount5, + /*OnlyUseCachedResults=*/true)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + MPM.run(M.get(), &MAM); + + // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); - EXPECT_EQ(3, FunctionPassRunCount); - EXPECT_EQ(5, AnalyzedInstrCount); -} + // Validate all function pass counter sets are the same. + EXPECT_EQ(3, FunctionPassRunCount1); + EXPECT_EQ(5, AnalyzedInstrCount1); + EXPECT_EQ(0, AnalyzedFunctionCount1); + EXPECT_EQ(3, FunctionPassRunCount2); + EXPECT_EQ(5, AnalyzedInstrCount2); + EXPECT_EQ(0, AnalyzedFunctionCount2); + EXPECT_EQ(3, FunctionPassRunCount3); + EXPECT_EQ(5, AnalyzedInstrCount3); + EXPECT_EQ(0, AnalyzedFunctionCount3); + EXPECT_EQ(3, FunctionPassRunCount4); + EXPECT_EQ(5, AnalyzedInstrCount4); + EXPECT_EQ(0, AnalyzedFunctionCount4); + EXPECT_EQ(3, FunctionPassRunCount5); + EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. + EXPECT_EQ(0, AnalyzedFunctionCount5); + + // Validate the analysis counters: + // first run over 3 functions, then module pass invalidates + // second run over 3 functions, nothing invalidates + // third run over 0 functions, but 1 function invalidated + // fourth run over 1 function + EXPECT_EQ(7, FunctionAnalysisRuns); + + EXPECT_EQ(1, ModuleAnalysisRuns); +} } diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp index 7c6d8ce..bebee15 100644 --- a/unittests/IR/PatternMatch.cpp +++ b/unittests/IR/PatternMatch.cpp @@ -13,253 +13,286 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Instructions.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/NoFolder.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" #include "gtest/gtest.h" +using namespace llvm; using namespace llvm::PatternMatch; -namespace llvm { namespace { -/// Ordered floating point minimum/maximum tests. - -static void m_OrdFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; +struct PatternMatchTest : ::testing::Test { + LLVMContext Ctx; + std::unique_ptr<Module> M; + Function *F; + BasicBlock *BB; + IRBuilder<true, NoFolder> IRB; + + PatternMatchTest() + : M(new Module("PatternMatchTestModule", Ctx)), + F(Function::Create( + FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false), + Function::ExternalLinkage, "f", M.get())), + BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {} +}; + +TEST_F(PatternMatchTest, OneUse) { + // Build up a little tree of values: + // + // One = (1 + 2) + 42 + // Two = One + 42 + // Leaf = (Two + 8) + (Two + 13) + Value *One = IRB.CreateAdd(IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2)), + IRB.getInt32(42)); + Value *Two = IRB.CreateAdd(One, IRB.getInt32(42)); + Value *Leaf = IRB.CreateAdd(IRB.CreateAdd(Two, IRB.getInt32(8)), + IRB.CreateAdd(Two, IRB.getInt32(13))); + Value *V; + + EXPECT_TRUE(m_OneUse(m_Value(V)).match(One)); + EXPECT_EQ(One, V); + + EXPECT_FALSE(m_OneUse(m_Value()).match(Two)); + EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf)); } -static void m_OrdFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - - - -TEST(PatternMatchTest, FloatingPointOrderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OLT. - Value *Cmp = Builder.CreateFCmpOLT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); // Test no match on OGT. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); // Test match on OGE with inverted select. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on OGT with inverted select. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointOrderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OGT. - Value *Cmp = Builder.CreateFCmpOGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); // Test no match on OLT. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); // Test match on OLE with inverted select. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); - - // Test match on OLT with inverted select. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); -} - -/// Unordered floating point minimum/maximum tests. - -static void m_UnordFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} -static void m_UnordFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + // Test match on OLT with inverted select. + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; } -TEST(PatternMatchTest, FloatingPointUnorderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test ULT. - Value *Cmp = Builder.CreateFCmpULT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); // Test no match on UGT. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); // Test match on UGE with inverted select. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on UGT with inverted select. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointUnorderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test UGT. - Value *Cmp = Builder.CreateFCmpUGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); // Test no match on ULT. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); // Test match on ULE with inverted select. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on ULT with inverted select. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); +} + +TEST_F(PatternMatchTest, OverflowingBinOps) { + Value *L = IRB.getInt32(1); + Value *R = IRB.getInt32(2); + Value *MatchL, *MatchR; + + EXPECT_TRUE( + m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_TRUE( + m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); } } // anonymous namespace. -} // llvm namespace. diff --git a/unittests/IR/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp new file mode 100644 index 0000000..15a0c22 --- /dev/null +++ b/unittests/IR/ValueHandleTest.cpp @@ -0,0 +1,407 @@ +//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "gtest/gtest.h" +#include <memory> + +using namespace llvm; + +namespace { + +class ValueHandle : public testing::Test { +protected: + Constant *ConstantV; + std::auto_ptr<BitCastInst> BitcastV; + + ValueHandle() : + ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), + BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { + } +}; + +class ConcreteCallbackVH : public CallbackVH { +public: + ConcreteCallbackVH(Value *V) : CallbackVH(V) {} +}; + +TEST_F(ValueHandle, WeakVH_BasicOperation) { + WeakVH WVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), WVH); + WVH = ConstantV; + EXPECT_EQ(ConstantV, WVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); +} + +TEST_F(ValueHandle, WeakVH_Comparisons) { + WeakVH BitcastWVH(BitcastV.get()); + WeakVH ConstantWVH(ConstantV); + + EXPECT_TRUE(BitcastWVH == BitcastWVH); + EXPECT_TRUE(BitcastV.get() == BitcastWVH); + EXPECT_TRUE(BitcastWVH == BitcastV.get()); + EXPECT_FALSE(BitcastWVH == ConstantWVH); + + EXPECT_TRUE(BitcastWVH != ConstantWVH); + EXPECT_TRUE(BitcastV.get() != ConstantWVH); + EXPECT_TRUE(BitcastWVH != ConstantV); + EXPECT_FALSE(BitcastWVH != BitcastWVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); +} + +TEST_F(ValueHandle, WeakVH_FollowsRAUW) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, WVH); + EXPECT_EQ(ConstantV, WVH_Copy); + EXPECT_EQ(ConstantV, WVH_Recreated); +} + +TEST_F(ValueHandle, WeakVH_NullOnDeletion) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV.reset(); + Value *null_value = NULL; + EXPECT_EQ(null_value, WVH); + EXPECT_EQ(null_value, WVH_Copy); + EXPECT_EQ(null_value, WVH_Recreated); +} + + +TEST_F(ValueHandle, AssertingVH_BasicOperation) { + AssertingVH<CastInst> AVH(BitcastV.get()); + CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. + + AssertingVH<Value> GenericAVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), GenericAVH); + GenericAVH = ConstantV; + EXPECT_EQ(ConstantV, GenericAVH); + + // Make sure I can call a method on the underlying CastInst. It + // doesn't matter which method. + EXPECT_FALSE(AVH->mayWriteToMemory()); + EXPECT_FALSE((*AVH).mayWriteToMemory()); +} + +TEST_F(ValueHandle, AssertingVH_Const) { + const CastInst *ConstBitcast = BitcastV.get(); + AssertingVH<const CastInst> AVH(ConstBitcast); + const CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. +} + +TEST_F(ValueHandle, AssertingVH_Comparisons) { + AssertingVH<Value> BitcastAVH(BitcastV.get()); + AssertingVH<Value> ConstantAVH(ConstantV); + + EXPECT_TRUE(BitcastAVH == BitcastAVH); + EXPECT_TRUE(BitcastV.get() == BitcastAVH); + EXPECT_TRUE(BitcastAVH == BitcastV.get()); + EXPECT_FALSE(BitcastAVH == ConstantAVH); + + EXPECT_TRUE(BitcastAVH != ConstantAVH); + EXPECT_TRUE(BitcastV.get() != ConstantAVH); + EXPECT_TRUE(BitcastAVH != ConstantV); + EXPECT_FALSE(BitcastAVH != BitcastAVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); +} + +TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { + AssertingVH<Value> AVH(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(BitcastV.get(), AVH); +} + +#ifdef NDEBUG + +TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { + EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>)); +} + +#else // !NDEBUG + +#ifdef GTEST_HAS_DEATH_TEST + +TEST_F(ValueHandle, AssertingVH_Asserts) { + AssertingVH<Value> AVH(BitcastV.get()); + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + AssertingVH<Value> Copy(AVH); + AVH = NULL; + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + Copy = NULL; + BitcastV.reset(); +} + +#endif // GTEST_HAS_DEATH_TEST + +#endif // NDEBUG + +TEST_F(ValueHandle, CallbackVH_BasicOperation) { + ConcreteCallbackVH CVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), CVH); + CVH = ConstantV; + EXPECT_EQ(ConstantV, CVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); +} + +TEST_F(ValueHandle, CallbackVH_Comparisons) { + ConcreteCallbackVH BitcastCVH(BitcastV.get()); + ConcreteCallbackVH ConstantCVH(ConstantV); + + EXPECT_TRUE(BitcastCVH == BitcastCVH); + EXPECT_TRUE(BitcastV.get() == BitcastCVH); + EXPECT_TRUE(BitcastCVH == BitcastV.get()); + EXPECT_FALSE(BitcastCVH == ConstantCVH); + + EXPECT_TRUE(BitcastCVH != ConstantCVH); + EXPECT_TRUE(BitcastV.get() != ConstantCVH); + EXPECT_TRUE(BitcastCVH != ConstantV); + EXPECT_FALSE(BitcastCVH != BitcastCVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + int AURWCalls; + + RecordingVH() : DeletedCalls(0), AURWCalls(0) {} + RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *) { AURWCalls++; } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); + BitcastV.reset(); + EXPECT_EQ(1, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + + RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecordingVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *new_value) { + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(NULL, RVH.AURWArgument); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(ConstantV, RVH.AURWArgument); +} + +TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { + class RecoveringVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + LLVMContext *Context; + + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + RecoveringVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + + private: + virtual void deleted() { + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); + setValPtr(NULL); + } + virtual void allUsesReplacedWith(Value *new_value) { + ASSERT_TRUE(NULL != getValPtr()); + EXPECT_EQ(1U, getValPtr()->getNumUses()); + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + // Normally, if a value has uses, deleting it will crash. However, we can use + // a CallbackVH to remove the uses before the check for no uses. + RecoveringVH RVH; + RVH = BitcastV.get(); + std::auto_ptr<BinaryOperator> BitcastUser( + BinaryOperator::CreateAdd(RVH, + Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); + EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); + BitcastV.reset(); // Would crash without the ValueHandler. + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), + BitcastUser->getOperand(0)); +} + +TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { + // When a CallbackVH modifies other ValueHandles in its callbacks, + // that shouldn't interfere with non-modified ValueHandles receiving + // their appropriate callbacks. + // + // We create the active CallbackVH in the middle of a palindromic + // arrangement of other VHs so that the bad behavior would be + // triggered in whichever order callbacks run. + + class DestroyingVH : public CallbackVH { + public: + std::unique_ptr<WeakVH> ToClear[2]; + DestroyingVH(Value *V) { + ToClear[0].reset(new WeakVH(V)); + setValPtr(V); + ToClear[1].reset(new WeakVH(V)); + } + virtual void deleted() { + ToClear[0].reset(); + ToClear[1].reset(); + CallbackVH::deleted(); + } + virtual void allUsesReplacedWith(Value *) { + ToClear[0].reset(); + ToClear[1].reset(); + } + }; + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2)); + } + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV.reset(); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2)); + } +} + +TEST_F(ValueHandle, AssertingVHCheckedLast) { + // If a CallbackVH exists to clear out a group of AssertingVHs on + // Value deletion, the CallbackVH should get a chance to do so + // before the AssertingVHs assert. + + class ClearingVH : public CallbackVH { + public: + AssertingVH<Value> *ToClear[2]; + ClearingVH(Value *V, + AssertingVH<Value> &A0, AssertingVH<Value> &A1) + : CallbackVH(V) { + ToClear[0] = &A0; + ToClear[1] = &A1; + } + + virtual void deleted() { + *ToClear[0] = 0; + *ToClear[1] = 0; + CallbackVH::deleted(); + } + }; + + AssertingVH<Value> A1, A2; + A1 = BitcastV.get(); + ClearingVH C(BitcastV.get(), A1, A2); + A2 = BitcastV.get(); + // C.deleted() should run first, clearing the two AssertingVHs, + // which should prevent them from asserting. + BitcastV.reset(); +} + +} diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 5aaf905..6fd87b1 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ValueMap.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -24,8 +23,8 @@ template<typename T> class ValueMapTest : public testing::Test { protected: Constant *ConstantV; - OwningPtr<BitCastInst> BitcastV; - OwningPtr<BinaryOperator> AddV; + std::unique_ptr<BitCastInst> BitcastV; + std::unique_ptr<BinaryOperator> AddV; ValueMapTest() : ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), @@ -117,7 +116,8 @@ TYPED_TEST(ValueMapTest, OperationsWork) { template<typename ExpectedType, typename VarType> void CompileAssertHasType(VarType) { - typedef char assert[is_same<ExpectedType, VarType>::value ? 1 : -1]; + static_assert(std::is_same<ExpectedType, VarType>::value, + "Not the same type"); } TYPED_TEST(ValueMapTest, Iteration) { diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index ebe23e8..d92bc82 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -45,7 +45,7 @@ TEST(ValueTest, UsedInBasicBlock) { TEST(GlobalTest, CreateAddressSpace) { LLVMContext &Ctx = getGlobalContext(); - OwningPtr<Module> M(new Module("TestModule", Ctx)); + std::unique_ptr<Module> M(new Module("TestModule", Ctx)); Type *Int8Ty = Type::getInt8Ty(Ctx); Type *Int32Ty = Type::getInt32Ty(Ctx); diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp index 31936c3..0a660a6 100644 --- a/unittests/IR/VerifierTest.cpp +++ b/unittests/IR/VerifierTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Verifier.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Verifier.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -42,7 +41,7 @@ TEST(VerifierTest, Branch_i1) { Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0); BI->setOperand(0, Zero32); - EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction)); + EXPECT_TRUE(verifyFunction(*F)); } TEST(VerifierTest, AliasUnnamedAddr) { @@ -58,8 +57,10 @@ TEST(VerifierTest, AliasUnnamedAddr) { "bar", Aliasee, &M); GA->setUnnamedAddr(true); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE( + StringRef(ErrorOS.str()).startswith("Alias cannot have unnamed_addr")); } TEST(VerifierTest, InvalidRetAttribute) { @@ -72,9 +73,10 @@ TEST(VerifierTest, InvalidRetAttribute) { Attribute::UWTable)); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error). - startswith("Attribute 'uwtable' only applies to functions!")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE(StringRef(ErrorOS.str()).startswith( + "Attribute 'uwtable' only applies to functions!")); } } |