aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests')
-rw-r--r--llvm/unittests/ADT/StringSwitchTest.cpp13
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp4
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/MemoryMapperTest.cpp10
-rw-r--r--llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp7
-rw-r--r--llvm/unittests/IR/ConstantFPRangeTest.cpp67
-rw-r--r--llvm/unittests/IR/InstructionsTest.cpp40
-rw-r--r--llvm/unittests/Support/CMakeLists.txt1
-rw-r--r--llvm/unittests/Support/Format.cpp56
-rw-r--r--llvm/unittests/Support/JobserverTest.cpp1
-rw-r--r--llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp51
-rw-r--r--llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp220
-rw-r--r--llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp9
12 files changed, 464 insertions, 15 deletions
diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp
index bcb1521..0fbf371 100644
--- a/llvm/unittests/ADT/StringSwitchTest.cpp
+++ b/llvm/unittests/ADT/StringSwitchTest.cpp
@@ -153,13 +153,14 @@ TEST(StringSwitchTest, EndsWithLower) {
}
TEST(StringSwitchTest, Cases) {
- enum class OSType { Windows, Linux, Unknown };
+ enum class OSType { Windows, Linux, MacOS, Unknown };
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
.Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
OSType::Windows)
.Cases("linux", "unix", "*nix", "posix", OSType::Linux)
+ .Cases({"macos", "osx"}, OSType::MacOS)
.Default(OSType::Unknown);
};
@@ -172,21 +173,26 @@ TEST(StringSwitchTest, Cases) {
EXPECT_EQ(OSType::Linux, Translate("*nix"));
EXPECT_EQ(OSType::Linux, Translate("posix"));
+ EXPECT_EQ(OSType::MacOS, Translate("macos"));
+ EXPECT_EQ(OSType::MacOS, Translate("osx"));
+
// Note that the whole null-terminator embedded string is required for the
// case to match.
EXPECT_EQ(OSType::Unknown, Translate("wind"));
EXPECT_EQ(OSType::Unknown, Translate("Windows"));
+ EXPECT_EQ(OSType::Unknown, Translate("MacOS"));
EXPECT_EQ(OSType::Unknown, Translate(""));
}
TEST(StringSwitchTest, CasesLower) {
- enum class OSType { Windows, Linux, Unknown };
+ enum class OSType { Windows, Linux, MacOS, Unknown };
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
.CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
OSType::Windows)
.CasesLower("linux", "unix", "*nix", "posix", OSType::Linux)
+ .CasesLower({"macos", "osx"}, OSType::MacOS)
.Default(OSType::Unknown);
};
@@ -202,6 +208,9 @@ TEST(StringSwitchTest, CasesLower) {
EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7)));
EXPECT_EQ(OSType::Linux, Translate("linux"));
+ EXPECT_EQ(OSType::MacOS, Translate("macOS"));
+ EXPECT_EQ(OSType::MacOS, Translate("OSX"));
+
EXPECT_EQ(OSType::Unknown, Translate("wind"));
EXPECT_EQ(OSType::Unknown, Translate(""));
}
diff --git a/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp
index c5e9d43..a5269f7 100644
--- a/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp
@@ -39,8 +39,8 @@ public:
return Mapper->initialize(AI, std::move(OnInitialized));
}
- char *prepare(ExecutorAddr Addr, size_t ContentSize) override {
- return Mapper->prepare(Addr, ContentSize);
+ char *prepare(LinkGraph &G, ExecutorAddr Addr, size_t ContentSize) override {
+ return Mapper->prepare(G, Addr, ContentSize);
}
void deinitialize(ArrayRef<ExecutorAddr> Allocations,
diff --git a/llvm/unittests/ExecutionEngine/Orc/MemoryMapperTest.cpp b/llvm/unittests/ExecutionEngine/Orc/MemoryMapperTest.cpp
index fea9eab..1174493 100644
--- a/llvm/unittests/ExecutionEngine/Orc/MemoryMapperTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/MemoryMapperTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Process.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -66,6 +67,9 @@ TEST(MemoryMapperTest, InitializeDeinitialize) {
{
std::unique_ptr<MemoryMapper> Mapper =
cantFail(InProcessMemoryMapper::Create());
+ jitlink::LinkGraph G("G", std::make_shared<SymbolStringPool>(),
+ Triple("x86_64-apple-darwin"), SubtargetFeatures(),
+ jitlink::getGenericEdgeKindName);
// We will do two separate allocations
auto PageSize = Mapper->getPageSize();
@@ -80,7 +84,7 @@ TEST(MemoryMapperTest, InitializeDeinitialize) {
{
// Provide working memory
- char *WA1 = Mapper->prepare(Mem1->Start, HW.size() + 1);
+ char *WA1 = Mapper->prepare(G, Mem1->Start, HW.size() + 1);
std::strcpy(WA1, HW.c_str());
}
@@ -105,7 +109,7 @@ TEST(MemoryMapperTest, InitializeDeinitialize) {
}
{
- char *WA2 = Mapper->prepare(Mem1->Start + PageSize, HW.size() + 1);
+ char *WA2 = Mapper->prepare(G, Mem1->Start + PageSize, HW.size() + 1);
std::strcpy(WA2, HW.c_str());
}
@@ -158,7 +162,7 @@ TEST(MemoryMapperTest, InitializeDeinitialize) {
auto Mem2 = reserve(*Mapper, PageSize);
EXPECT_THAT_ERROR(Mem2.takeError(), Succeeded());
- char *WA = Mapper->prepare(Mem2->Start, HW.size() + 1);
+ char *WA = Mapper->prepare(G, Mem2->Start, HW.size() + 1);
std::strcpy(WA, HW.c_str());
MemoryMapper::AllocInfo Alloc3;
diff --git a/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp
index 700500f..7775f3c 100644
--- a/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp
@@ -8,6 +8,7 @@
#include "OrcTestCommon.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
@@ -67,12 +68,16 @@ TEST(SharedMemoryMapperTest, MemReserveInitializeDeinitializeRelease) {
auto PageSize = Mapper->getPageSize();
size_t ReqSize = PageSize;
+ jitlink::LinkGraph G("G", std::make_shared<SymbolStringPool>(),
+ Triple("x86_64-apple-darwin"), SubtargetFeatures(),
+ jitlink::getGenericEdgeKindName);
Mapper->reserve(ReqSize, [&](Expected<ExecutorAddrRange> Result) {
EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
auto Reservation = std::move(*Result);
{
- char *Addr = Mapper->prepare(Reservation.Start, TestString.size() + 1);
+ char *Addr =
+ Mapper->prepare(G, Reservation.Start, TestString.size() + 1);
std::strcpy(Addr, TestString.c_str());
}
MemoryMapper::AllocInfo AI;
diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp
index cf9b31c..2431db9 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -8,6 +8,7 @@
#include "llvm/IR/ConstantFPRange.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "gtest/gtest.h"
@@ -1065,4 +1066,70 @@ TEST_F(ConstantFPRangeTest, sub) {
#endif
}
+TEST_F(ConstantFPRangeTest, flushDenormals) {
+ const fltSemantics &FP8Sem = APFloat::Float8E4M3();
+ APFloat NormalVal = APFloat::getSmallestNormalized(FP8Sem);
+ APFloat Subnormal1 = NormalVal;
+ Subnormal1.next(/*nextDown=*/true);
+ APFloat Subnormal2 = APFloat::getSmallest(FP8Sem);
+ APFloat ZeroVal = APFloat::getZero(FP8Sem);
+ APFloat EdgeValues[8] = {-NormalVal, -Subnormal1, -Subnormal2, -ZeroVal,
+ ZeroVal, Subnormal2, Subnormal1, NormalVal};
+ constexpr DenormalMode::DenormalModeKind Modes[4] = {
+ DenormalMode::IEEE, DenormalMode::PreserveSign,
+ DenormalMode::PositiveZero, DenormalMode::Dynamic};
+ for (uint32_t I = 0; I != 8; ++I) {
+ for (uint32_t J = I; J != 8; ++J) {
+ ConstantFPRange OriginCR =
+ ConstantFPRange::getNonNaN(EdgeValues[I], EdgeValues[J]);
+ for (auto Mode : Modes) {
+ StringRef ModeName = denormalModeKindName(Mode);
+ ConstantFPRange FlushedCR = OriginCR;
+ FlushedCR.flushDenormals(Mode);
+
+ ConstantFPRange Expected = ConstantFPRange::getEmpty(FP8Sem);
+ auto CheckFlushedV = [&](const APFloat &V, const APFloat &FlushedV) {
+ EXPECT_TRUE(FlushedCR.contains(FlushedV))
+ << "Wrong result for flushDenormal(" << V << ", " << ModeName
+ << "). The result " << FlushedCR << " should contain "
+ << FlushedV;
+ if (!Expected.contains(FlushedV))
+ Expected = Expected.unionWith(ConstantFPRange(FlushedV));
+ };
+ EnumerateValuesInConstantFPRange(
+ OriginCR,
+ [&](const APFloat &V) {
+ if (V.isDenormal()) {
+ switch (Mode) {
+ case DenormalMode::IEEE:
+ break;
+ case DenormalMode::PreserveSign:
+ CheckFlushedV(V, APFloat::getZero(FP8Sem, V.isNegative()));
+ break;
+ case DenormalMode::PositiveZero:
+ CheckFlushedV(V, APFloat::getZero(FP8Sem));
+ break;
+ case DenormalMode::Dynamic:
+ // PreserveSign
+ CheckFlushedV(V, APFloat::getZero(FP8Sem, V.isNegative()));
+ // PositiveZero
+ CheckFlushedV(V, APFloat::getZero(FP8Sem));
+ break;
+ default:
+ llvm_unreachable("unknown denormal mode");
+ }
+ }
+ // It is not mandated that flushing to zero occurs.
+ CheckFlushedV(V, V);
+ },
+ /*IgnoreNaNPayload=*/true);
+ EXPECT_EQ(FlushedCR, Expected)
+ << "Suboptimal result for flushDenormal(" << OriginCR << ", "
+ << ModeName << "). Expected " << Expected << ", but got "
+ << FlushedCR;
+ }
+ }
+ }
+}
+
} // anonymous namespace
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index fe9e7e8..f4693bf 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -606,12 +606,14 @@ TEST(InstructionTest, ConstrainedTrans) {
TEST(InstructionsTest, isEliminableCastPair) {
LLVMContext C;
- DataLayout DL1("p1:32:32");
+ DataLayout DL1("p1:32:32-p2:64:64:64:32");
Type *Int16Ty = Type::getInt16Ty(C);
+ Type *Int32Ty = Type::getInt32Ty(C);
Type *Int64Ty = Type::getInt64Ty(C);
Type *PtrTy64 = PointerType::get(C, 0);
Type *PtrTy32 = PointerType::get(C, 1);
+ Type *PtrTy64_32 = PointerType::get(C, 2);
// Source and destination pointers have same size -> bitcast.
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
@@ -637,6 +639,42 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int64Ty, &DL1),
0U);
+ // Destination larger than source. Pointer type same as destination.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int16Ty, PtrTy64,
+ Int64Ty, &DL1),
+ CastInst::ZExt);
+
+ // Destination larger than source. Pointer type different from destination.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int16Ty, PtrTy32,
+ Int64Ty, &DL1),
+ CastInst::ZExt);
+
+ // Destination smaller than source. Pointer type same as source.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int64Ty, PtrTy64,
+ Int16Ty, &DL1),
+ CastInst::Trunc);
+
+ // Destination smaller than source. Pointer type different from source.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int64Ty, PtrTy32,
+ Int16Ty, &DL1),
+ CastInst::Trunc);
+
+ // ptrtoaddr with address size != pointer size. Truncating case.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToAddr, Int64Ty,
+ PtrTy64_32, Int32Ty, &DL1),
+ CastInst::Trunc);
+
+ // ptrtoaddr with address size != pointer size. Non-truncating case.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToAddr, Int32Ty,
+ PtrTy64_32, Int32Ty, &DL1),
+ CastInst::BitCast);
+
// Test that we don't eliminate bitcasts between different address spaces,
// or if we don't have available pointer size information.
DataLayout DL2("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 25efa00..21f10eb 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -44,6 +44,7 @@ add_llvm_unittest(SupportTests
ExtensibleRTTITest.cpp
FileCollectorTest.cpp
FileOutputBufferTest.cpp
+ Format.cpp
FormatVariadicTest.cpp
FSUniqueIDTest.cpp
GenericDomTreeTest.cpp
diff --git a/llvm/unittests/Support/Format.cpp b/llvm/unittests/Support/Format.cpp
new file mode 100644
index 0000000..c4e421f
--- /dev/null
+++ b/llvm/unittests/Support/Format.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Format.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <typename FormatTy>
+std::string printToString(unsigned MaxN, FormatTy &&Fmt) {
+ std::vector<char> Dst(MaxN + 2);
+ int N = Fmt.snprint(Dst.data(), Dst.size());
+ Dst.back() = 0;
+ return N < 0 ? "" : Dst.data();
+}
+
+template <typename Expected, typename Arg>
+constexpr bool checkDecayTypeEq(const Arg &arg) {
+ return std::is_same_v<detail::decay_if_c_char_array_t<Arg>, Expected>;
+}
+
+TEST(Format, DecayIfCCharArray) {
+ char Array[] = "Array";
+ const char ConstArray[] = "ConstArray";
+ char PtrBuf[] = "Ptr";
+ char *Ptr = PtrBuf;
+ const char *PtrToConst = "PtrToConst";
+
+ EXPECT_EQ(" Literal", printToString(20, format("%15s", "Literal")));
+ EXPECT_EQ(" Array", printToString(20, format("%15s", Array)));
+ EXPECT_EQ(" ConstArray", printToString(20, format("%15s", ConstArray)));
+ EXPECT_EQ(" Ptr", printToString(20, format("%15s", Ptr)));
+ EXPECT_EQ(" PtrToConst", printToString(20, format("%15s", PtrToConst)));
+
+ EXPECT_TRUE(checkDecayTypeEq<const char *>("Literal"));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(Array));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(ConstArray));
+ EXPECT_TRUE(checkDecayTypeEq<char *>(Ptr));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(PtrToConst));
+ EXPECT_TRUE(checkDecayTypeEq<char>(PtrToConst[0]));
+ EXPECT_TRUE(
+ checkDecayTypeEq<const char *>(static_cast<const char *>("Literal")));
+
+ wchar_t WCharArray[] = L"WCharArray";
+ EXPECT_TRUE(checkDecayTypeEq<wchar_t[11]>(WCharArray));
+ EXPECT_TRUE(checkDecayTypeEq<wchar_t>(WCharArray[0]));
+}
+
+} // namespace
diff --git a/llvm/unittests/Support/JobserverTest.cpp b/llvm/unittests/Support/JobserverTest.cpp
index ddee023..d274458 100644
--- a/llvm/unittests/Support/JobserverTest.cpp
+++ b/llvm/unittests/Support/JobserverTest.cpp
@@ -355,6 +355,7 @@ TEST_F(JobserverStrategyTest, ThreadPoolConcurrencyIsLimited) {
int CurrentActive = ++ActiveTasks;
LLVM_DEBUG(dbgs() << "Task " << i << ": Active tasks: " << CurrentActive
<< "\n");
+ (void)i;
int OldMax = MaxActiveTasks.load();
while (CurrentActive > OldMax)
MaxActiveTasks.compare_exchange_weak(OldMax, CurrentActive);
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index c74d157..5ac4c53 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -177,6 +177,57 @@ TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_VASHR) {
EXPECT_EQ(DAG->ComputeNumSignBits(Fr2), 5u);
}
+TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SUB) {
+ SDLoc Loc;
+ auto IntVT = EVT::getIntegerVT(Context, 8);
+ auto N0 = DAG->getConstant(0x00, Loc, IntVT);
+ auto N1 = DAG->getConstant(0x01, Loc, IntVT);
+ auto N5 = DAG->getConstant(0x05, Loc, IntVT);
+ auto Nsign1 = DAG->getConstant(0x55, Loc, IntVT);
+ auto UnknownOp = DAG->getRegister(0, IntVT);
+ auto Mask = DAG->getConstant(0x1e, Loc, IntVT);
+ auto Nsign3 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp);
+ // RHS early out
+ // Nsign1 = 01010101
+ // Nsign3 = 000????0
+ auto OpRhsEo = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign3, Nsign1);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpRhsEo), 1u);
+
+ // Neg 0
+ // N0 = 00000000
+ auto OpNegZero = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N0);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNegZero), 8u);
+
+ // Neg 1
+ // N0 = 00000000
+ // N1 = 00000001
+ auto OpNegOne = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNegOne), 8u);
+
+ // Neg 5
+ // N0 = 00000000
+ // N5 = 00000101
+ auto OpNegFive = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N5);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNegFive), 5u);
+
+ // Non negative
+ // N0 = 00000000
+ // Nsign3 = 000????0
+ auto OpNonNeg = DAG->getNode(ISD::SUB, Loc, IntVT, N0, Nsign3);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNonNeg), 3u);
+
+ // LHS early out
+ // Nsign1 = 01010101
+ // Nsign3 = 000????0
+ auto OpLhsEo = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign1, Nsign3);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpLhsEo), 1u);
+
+ // Nsign3 = 000????0
+ // N5 = 00000101
+ auto Op = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign3, N5);
+ EXPECT_EQ(DAG->ComputeNumSignBits(Op), 2u);
+}
+
TEST_F(AArch64SelectionDAGTest, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR) {
TargetLowering TL(*TM);
diff --git a/llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp b/llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp
index 841f44c..716f5f2 100644
--- a/llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp
+++ b/llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp
@@ -308,3 +308,223 @@ TEST(SSAUpdaterBulk, TwoBBLoop) {
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I);
}
+
+TEST(SSAUpdaterBulk, SimplifyPHIs) {
+ const char *IR = R"(
+ define void @main(i32 %val, i1 %cond) {
+ entry:
+ br i1 %cond, label %left, label %right
+ left:
+ %add = add i32 %val, 1
+ br label %exit
+ right:
+ %sub = sub i32 %val, 1
+ br label %exit
+ exit:
+ %phi = phi i32 [ %sub, %right ], [ %add, %left ]
+ %cmp = icmp slt i32 0, 42
+ ret void
+ }
+ )";
+
+ llvm::LLVMContext Context;
+ llvm::SMDiagnostic Err;
+ std::unique_ptr<llvm::Module> M = llvm::parseAssemblyString(IR, Err, Context);
+ ASSERT_NE(M, nullptr) << "Failed to parse IR: " << Err.getMessage();
+
+ Function *F = M->getFunction("main");
+ auto *Entry = &F->getEntryBlock();
+ auto *Left = Entry->getTerminator()->getSuccessor(0);
+ auto *Right = Entry->getTerminator()->getSuccessor(1);
+ auto *Exit = Left->getSingleSuccessor();
+ auto *Val = &*F->arg_begin();
+ auto *Phi = &Exit->front();
+ auto *Cmp = &*std::next(Exit->begin());
+ auto *Add = &Left->front();
+ auto *Sub = &Right->front();
+
+ SSAUpdaterBulk Updater;
+ Type *I32Ty = Type::getInt32Ty(Context);
+
+ // Use %val directly instead of creating a phi.
+ unsigned ValVar = Updater.AddVariable("Val", I32Ty);
+ Updater.AddAvailableValue(ValVar, Left, Val);
+ Updater.AddAvailableValue(ValVar, Right, Val);
+ Updater.AddUse(ValVar, &Cmp->getOperandUse(0));
+
+ // Use existing %phi for %add and %sub values.
+ unsigned AddSubVar = Updater.AddVariable("AddSub", I32Ty);
+ Updater.AddAvailableValue(AddSubVar, Left, Add);
+ Updater.AddAvailableValue(AddSubVar, Right, Sub);
+ Updater.AddUse(AddSubVar, &Cmp->getOperandUse(1));
+
+ auto ExitSizeBefore = Exit->size();
+ DominatorTree DT(*F);
+ Updater.RewriteAndOptimizeAllUses(DT);
+
+ // Output for Exit->dump():
+ // exit: ; preds = %right, %left
+ // %phi = phi i32 [ %sub, %right ], [ %add, %left ]
+ // %cmp = icmp slt i32 %val, %phi
+ // ret void
+
+ ASSERT_EQ(Exit->size(), ExitSizeBefore);
+ ASSERT_EQ(&Exit->front(), Phi);
+ EXPECT_EQ(Val, Cmp->getOperand(0));
+ EXPECT_EQ(Phi, Cmp->getOperand(1));
+}
+
+bool EliminateNewDuplicatePHINodes(BasicBlock *BB,
+ BasicBlock::phi_iterator FirstExistingPN);
+
+// Helper to run both versions on the same input.
+static void RunEliminateNewDuplicatePHINode(
+ const char *AsmText,
+ std::function<void(BasicBlock &,
+ bool(BasicBlock *BB, BasicBlock::phi_iterator))>
+ Check) {
+ LLVMContext C;
+
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(AsmText, Err, C);
+ if (!M) {
+ Err.print("UtilsTests", errs());
+ return;
+ }
+
+ Function *F = M->getFunction("main");
+ auto BBIt = std::find_if(F->begin(), F->end(), [](const BasicBlock &Block) {
+ return Block.getName() == "testbb";
+ });
+ ASSERT_NE(BBIt, F->end());
+ Check(*BBIt, EliminateNewDuplicatePHINodes);
+}
+
+static BasicBlock::phi_iterator getPhiIt(BasicBlock &BB, unsigned Idx) {
+ return std::next(BB.phis().begin(), Idx);
+}
+
+static PHINode *getPhi(BasicBlock &BB, unsigned Idx) {
+ return &*getPhiIt(BB, Idx);
+}
+
+static int getNumPHIs(BasicBlock &BB) {
+ return std::distance(BB.phis().begin(), BB.phis().end());
+}
+
+TEST(SSAUpdaterBulk, EliminateNewDuplicatePHINodes_OrderExisting) {
+ RunEliminateNewDuplicatePHINode(R"(
+ define void @main() {
+ entry:
+ br label %testbb
+ testbb:
+ %np0 = phi i32 [ 1, %entry ]
+ %np1 = phi i32 [ 1, %entry ]
+ %ep0 = phi i32 [ 1, %entry ]
+ %ep1 = phi i32 [ 1, %entry ]
+ %u = add i32 %np0, %np1
+ ret void
+ }
+ )", [](BasicBlock &BB, auto *ENDPN) {
+ AssertingVH<PHINode> EP0 = getPhi(BB, 2);
+ AssertingVH<PHINode> EP1 = getPhi(BB, 3);
+ EXPECT_TRUE(ENDPN(&BB, getPhiIt(BB, 2)));
+ // Expected:
+ // %ep0 = phi i32 [ 1, %entry ]
+ // %ep1 = phi i32 [ 1, %entry ]
+ // %u = add i32 %ep0, %ep0
+ EXPECT_EQ(getNumPHIs(BB), 2);
+ Instruction &Add = *BB.getFirstNonPHIIt();
+ EXPECT_EQ(Add.getOperand(0), EP0);
+ EXPECT_EQ(Add.getOperand(1), EP0);
+ (void)EP1; // Avoid "unused" warning.
+ });
+}
+
+TEST(SSAUpdaterBulk, EliminateNewDuplicatePHINodes_OrderNew) {
+ RunEliminateNewDuplicatePHINode(R"(
+ define void @main() {
+ entry:
+ br label %testbb
+ testbb:
+ %np0 = phi i32 [ 1, %entry ]
+ %np1 = phi i32 [ 1, %entry ]
+ %ep0 = phi i32 [ 2, %entry ]
+ %ep1 = phi i32 [ 2, %entry ]
+ %u = add i32 %np0, %np1
+ ret void
+ }
+ )", [](BasicBlock &BB, auto *ENDPN) {
+ AssertingVH<PHINode> NP0 = getPhi(BB, 0);
+ AssertingVH<PHINode> EP0 = getPhi(BB, 2);
+ AssertingVH<PHINode> EP1 = getPhi(BB, 3);
+ EXPECT_TRUE(ENDPN(&BB, getPhiIt(BB, 2)));
+ // Expected:
+ // %np0 = phi i32 [ 1, %entry ]
+ // %ep0 = phi i32 [ 2, %entry ]
+ // %ep1 = phi i32 [ 2, %entry ]
+ // %u = add i32 %np0, %np0
+ EXPECT_EQ(getNumPHIs(BB), 3);
+ Instruction &Add = *BB.getFirstNonPHIIt();
+ EXPECT_EQ(Add.getOperand(0), NP0);
+ EXPECT_EQ(Add.getOperand(1), NP0);
+ (void)EP0;
+ (void)EP1; // Avoid "unused" warning.
+ });
+}
+
+TEST(SSAUpdaterBulk, EliminateNewDuplicatePHINodes_NewRefExisting) {
+ RunEliminateNewDuplicatePHINode(R"(
+ define void @main() {
+ entry:
+ br label %testbb
+ testbb:
+ %np0 = phi i32 [ 1, %entry ], [ %ep0, %testbb ]
+ %np1 = phi i32 [ 1, %entry ], [ %ep1, %testbb ]
+ %ep0 = phi i32 [ 1, %entry ], [ %ep0, %testbb ]
+ %ep1 = phi i32 [ 1, %entry ], [ %ep1, %testbb ]
+ %u = add i32 %np0, %np1
+ br label %testbb
+ }
+ )", [](BasicBlock &BB, auto *ENDPN) {
+ AssertingVH<PHINode> EP0 = getPhi(BB, 2);
+ AssertingVH<PHINode> EP1 = getPhi(BB, 3);
+ EXPECT_TRUE(ENDPN(&BB, getPhiIt(BB, 2)));
+ // Expected:
+ // %ep0 = phi i32 [ 1, %entry ], [ %ep0, %testbb ]
+ // %ep1 = phi i32 [ 1, %entry ], [ %ep1, %testbb ]
+ // %u = add i32 %ep0, %ep1
+ EXPECT_EQ(getNumPHIs(BB), 2);
+ Instruction &Add = *BB.getFirstNonPHIIt();
+ EXPECT_EQ(Add.getOperand(0), EP0);
+ EXPECT_EQ(Add.getOperand(1), EP1);
+ });
+}
+
+TEST(SSAUpdaterBulk, EliminateNewDuplicatePHINodes_ExistingRefNew) {
+ RunEliminateNewDuplicatePHINode(R"(
+ define void @main() {
+ entry:
+ br label %testbb
+ testbb:
+ %np0 = phi i32 [ 1, %entry ], [ %np0, %testbb ]
+ %np1 = phi i32 [ 1, %entry ], [ %np1, %testbb ]
+ %ep0 = phi i32 [ 1, %entry ], [ %np0, %testbb ]
+ %ep1 = phi i32 [ 1, %entry ], [ %np1, %testbb ]
+ %u = add i32 %np0, %np1
+ br label %testbb
+ }
+ )", [](BasicBlock &BB, auto *ENDPN) {
+ AssertingVH<PHINode> EP0 = getPhi(BB, 2);
+ AssertingVH<PHINode> EP1 = getPhi(BB, 3);
+ EXPECT_TRUE(ENDPN(&BB, getPhiIt(BB, 2)));
+ // Expected:
+ // %ep0 = phi i32 [ 1, %entry ], [ %ep0, %testbb ]
+ // %ep1 = phi i32 [ 1, %entry ], [ %ep1, %testbb ]
+ // %u = add i32 %ep0, %ep1
+ EXPECT_EQ(getNumPHIs(BB), 2);
+ Instruction &Add = *BB.getFirstNonPHIIt();
+ EXPECT_EQ(Add.getOperand(0), EP0);
+ EXPECT_EQ(Add.getOperand(1), EP1);
+ });
+}
diff --git a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
index 55b68f5..2a0f500 100644
--- a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
@@ -45,8 +45,7 @@ TEST_F(VPDominatorTreeTest, DominanceNoRegionsTest) {
VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
- VPDominatorTree VPDT;
- VPDT.recalculate(Plan);
+ VPDominatorTree VPDT(Plan);
EXPECT_TRUE(VPDT.dominates(VPBB1, VPBB4));
EXPECT_FALSE(VPDT.dominates(VPBB4, VPBB1));
@@ -118,8 +117,7 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) {
VPBlockUtils::connectBlocks(R1, R2);
VPBlockUtils::connectBlocks(R2, Plan.getScalarHeader());
- VPDominatorTree VPDT;
- VPDT.recalculate(Plan);
+ VPDominatorTree VPDT(Plan);
checkDomChildren(VPDT, R1, {R1BB1});
checkDomChildren(VPDT, R1BB1, {R1BB2, R1BB4, R1BB3});
@@ -197,8 +195,7 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) {
VPBlockUtils::connectBlocks(R1, VPBB2);
VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader());
- VPDominatorTree VPDT;
- VPDT.recalculate(Plan);
+ VPDominatorTree VPDT(Plan);
checkDomChildren(VPDT, VPBB1, {R1});
checkDomChildren(VPDT, R1, {R1BB1});