diff options
Diffstat (limited to 'llvm/unittests')
31 files changed, 1326 insertions, 180 deletions
diff --git a/llvm/unittests/ADT/BitFieldsTest.cpp b/llvm/unittests/ADT/BitFieldsTest.cpp index 3062d5d..ae541fe 100644 --- a/llvm/unittests/ADT/BitFieldsTest.cpp +++ b/llvm/unittests/ADT/BitFieldsTest.cpp @@ -247,8 +247,8 @@ TEST(BitfieldsTest, ValueTooBigBounded) { Bitfield::set<A>(Storage, 0); Bitfield::set<A>(Storage, -1); Bitfield::set<A>(Storage, -2); - EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 2), "value is too big"); - EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, -3), "value is too small"); + EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, 2), "value is out of range"); + EXPECT_DEBUG_DEATH(Bitfield::set<A>(Storage, -3), "value is out of range"); } #endif diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index 137dd43..e2e778f 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -127,24 +127,24 @@ public: return c0.getValue() == c1.getValue(); } - friend bool LLVM_ATTRIBUTE_UNUSED operator!=(const Constructable &c0, - const Constructable &c1) { + [[maybe_unused]] friend bool operator!=(const Constructable &c0, + const Constructable &c1) { return c0.getValue() != c1.getValue(); } friend bool operator<(const Constructable &c0, const Constructable &c1) { return c0.getValue() < c1.getValue(); } - friend bool LLVM_ATTRIBUTE_UNUSED operator<=(const Constructable &c0, - const Constructable &c1) { + [[maybe_unused]] friend bool operator<=(const Constructable &c0, + const Constructable &c1) { return c0.getValue() <= c1.getValue(); } - friend bool LLVM_ATTRIBUTE_UNUSED operator>(const Constructable &c0, - const Constructable &c1) { + [[maybe_unused]] friend bool operator>(const Constructable &c0, + const Constructable &c1) { return c0.getValue() > c1.getValue(); } - friend bool LLVM_ATTRIBUTE_UNUSED operator>=(const Constructable &c0, - const Constructable &c1) { + [[maybe_unused]] friend bool operator>=(const Constructable &c0, + const Constructable &c1) { return c0.getValue() >= c1.getValue(); } }; diff --git a/llvm/unittests/ADT/StringExtrasTest.cpp b/llvm/unittests/ADT/StringExtrasTest.cpp index fbaed38..af88f889 100644 --- a/llvm/unittests/ADT/StringExtrasTest.cpp +++ b/llvm/unittests/ADT/StringExtrasTest.cpp @@ -290,6 +290,12 @@ TEST(StringExtrasTest, ListSeparator) { EXPECT_EQ(S, ""); S = LS2; EXPECT_EQ(S, " "); + + ListSeparator LS3(",", "{"); + S = LS3; + EXPECT_EQ(S, "{"); + S = LS3; + EXPECT_EQ(S, ","); } TEST(StringExtrasTest, toStringAPInt) { 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/ADT/TypeTraitsTest.cpp b/llvm/unittests/ADT/TypeTraitsTest.cpp index a56aa7e..f9b8d6d 100644 --- a/llvm/unittests/ADT/TypeTraitsTest.cpp +++ b/llvm/unittests/ADT/TypeTraitsTest.cpp @@ -40,9 +40,7 @@ struct Foo { struct CheckMethodPointer : CheckFunctionTraits<decltype(&Foo::func)> {}; /// Test lambda references. -LLVM_ATTRIBUTE_UNUSED auto lambdaFunc = [](const int &v) -> bool { - return true; -}; +[[maybe_unused]] auto lambdaFunc = [](const int &v) -> bool { return true; }; struct CheckLambda : CheckFunctionTraits<decltype(lambdaFunc)> {}; } // end anonymous namespace diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp index ee37fad..8c3a213 100644 --- a/llvm/unittests/Analysis/DXILResourceTest.cpp +++ b/llvm/unittests/Analysis/DXILResourceTest.cpp @@ -369,10 +369,8 @@ TEST(DXILResource, AnnotationsAndMetadata) { { StructType *CBufStruct = StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0"); - TargetExtType *CBufLayoutType = - llvm::TargetExtType::get(Context, "dx.Layout", CBufStruct, {32, 0, 16}); ResourceTypeInfo RTI( - llvm::TargetExtType::get(Context, "dx.CBuffer", CBufLayoutType)); + llvm::TargetExtType::get(Context, "dx.CBuffer", CBufStruct)); EXPECT_EQ(RTI.getResourceClass(), ResourceClass::CBuffer); EXPECT_EQ(RTI.getCBufferSize(DL), 32u); EXPECT_EQ(RTI.getResourceKind(), ResourceKind::CBuffer); diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp index 1a68823..5d7eded 100644 --- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -11,6 +11,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/Analysis/ScalarEvolutionPatternMatch.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" @@ -26,6 +27,8 @@ namespace llvm { +using namespace SCEVPatternMatch; + // We use this fixture to ensure that we clean up ScalarEvolution before // deleting the PassManager. class ScalarEvolutionsTest : public testing::Test { @@ -64,11 +67,6 @@ static std::optional<APInt> computeConstantDifference(ScalarEvolution &SE, return SE.computeConstantDifference(LHS, RHS); } - static bool matchURem(ScalarEvolution &SE, const SCEV *Expr, const SCEV *&LHS, - const SCEV *&RHS) { - return SE.matchURem(Expr, LHS, RHS); - } - static bool isImpliedCond( ScalarEvolution &SE, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, @@ -1524,7 +1522,7 @@ TEST_F(ScalarEvolutionsTest, MatchURem) { auto *URemI = getInstructionByName(F, N); auto *S = SE.getSCEV(URemI); const SCEV *LHS, *RHS; - EXPECT_TRUE(matchURem(SE, S, LHS, RHS)); + EXPECT_TRUE(match(S, m_scev_URem(m_SCEV(LHS), m_SCEV(RHS), SE))); EXPECT_EQ(LHS, SE.getSCEV(URemI->getOperand(0))); EXPECT_EQ(RHS, SE.getSCEV(URemI->getOperand(1))); EXPECT_EQ(LHS->getType(), S->getType()); @@ -1537,7 +1535,7 @@ TEST_F(ScalarEvolutionsTest, MatchURem) { auto *URem1 = getInstructionByName(F, "rem4"); auto *S = SE.getSCEV(Ext); const SCEV *LHS, *RHS; - EXPECT_TRUE(matchURem(SE, S, LHS, RHS)); + EXPECT_TRUE(match(S, m_scev_URem(m_SCEV(LHS), m_SCEV(RHS), SE))); EXPECT_NE(LHS, SE.getSCEV(URem1->getOperand(0))); // RHS and URem1->getOperand(1) have different widths, so compare the // integer values. diff --git a/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp b/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp index 3ab2caf..57e15a4 100644 --- a/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp +++ b/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp @@ -39,20 +39,21 @@ TEST(DataLayoutUpgradeTest, ValidDataLayoutUpgrade) { "64-i128:128-n32:64-S128-Fn32"); // Check that AMDGPU targets add -G1 if it's not present. - EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32", "r600"), "e-p:32:32-G1"); + EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32", "r600"), "m:e-e-p:32:32-G1"); // and that ANDGCN adds p7 and p8 as well. EXPECT_EQ(UpgradeDataLayoutString("e-p:64:64", "amdgcn"), - "e-p:64:64-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:" - "256:256:32"); + "m:e-e-p:64:64-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:" + "192:256:256:32"); EXPECT_EQ(UpgradeDataLayoutString("e-p:64:64-G1", "amdgcn"), - "e-p:64:64-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:" - "256:256:32"); + "m:e-e-p:64:64-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:" + "192:256:256:32"); // Check that the old AMDGCN p8:128:128 definition is upgraded EXPECT_EQ(UpgradeDataLayoutString("e-p:64:64-p8:128:128-G1", "amdgcn"), - "e-p:64:64-p8:128:128:128:48-G1-ni:7:8:9-p7:160:256:256:32-" - "p9:192:256:256:32"); + "m:e-e-p:64:64-p8:128:128:128:48-G1-ni:7:8:9-p7:160:256:256:32-p9:" + "192:256:256:32"); // but that r600 does not. - EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32-G1", "r600"), "e-p:32:32-G1"); + EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32-G1", "r600"), + "m:e-e-p:32:32-G1"); // Ensure that the non-integral direction for address space 8 doesn't get // added in to pointer declarations. @@ -62,11 +63,10 @@ TEST(DataLayoutUpgradeTest, ValidDataLayoutUpgrade) { "64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-" "v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7", "amdgcn"), - "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-" - "v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:" + "m:e-e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:" + "64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:" "1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:" - "128:48-" - "p9:192:256:256:32"); + "128:48-p9:192:256:256:32"); // Check that RISCV64 upgrades -n64 to -n32:64. EXPECT_EQ(UpgradeDataLayoutString("e-m:e-p:64:64-i64:64-i128:128-n64-S128", @@ -147,28 +147,29 @@ TEST(DataLayoutUpgradeTest, NoDataLayoutUpgrade) { "64-S128-Fn32"); // Check that AMDGPU targets don't add -G1 if there is already a -G flag. - EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32-G2", "r600"), "e-p:32:32-G2"); - EXPECT_EQ(UpgradeDataLayoutString("G2", "r600"), "G2"); + EXPECT_EQ(UpgradeDataLayoutString("e-p:32:32-G2", "r600"), + "m:e-e-p:32:32-G2"); + EXPECT_EQ(UpgradeDataLayoutString("G2", "r600"), "m:e-G2"); EXPECT_EQ(UpgradeDataLayoutString("e-p:64:64-G2", "amdgcn"), - "e-p:64:64-G2-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:" - "256:256:32"); + "m:e-e-p:64:64-G2-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:" + "192:256:256:32"); EXPECT_EQ(UpgradeDataLayoutString("G2-e-p:64:64", "amdgcn"), - "G2-e-p:64:64-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:" - "256:256:32"); + "m:e-G2-e-p:64:64-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:" + "192:256:256:32"); EXPECT_EQ(UpgradeDataLayoutString("e-p:64:64-G0", "amdgcn"), - "e-p:64:64-G0-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:" - "256:256:32"); + "m:e-e-p:64:64-G0-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:" + "192:256:256:32"); // Check that AMDGCN targets don't add already declared address space 7. EXPECT_EQ( UpgradeDataLayoutString("e-p:64:64-p7:64:64", "amdgcn"), - "e-p:64:64-p7:64:64-G1-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); + "m:e-e-p:64:64-p7:64:64-G1-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); EXPECT_EQ( UpgradeDataLayoutString("p7:64:64-G2-e-p:64:64", "amdgcn"), - "p7:64:64-G2-e-p:64:64-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); + "m:e-p7:64:64-G2-e-p:64:64-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); EXPECT_EQ( UpgradeDataLayoutString("e-p:64:64-p7:64:64-G1", "amdgcn"), - "e-p:64:64-p7:64:64-G1-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); + "m:e-e-p:64:64-p7:64:64-G1-ni:7:8:9-p8:128:128:128:48-p9:192:256:256:32"); // Check that SPIR & SPIRV targets don't add -G1 if there is already a -G // flag. @@ -198,10 +199,10 @@ TEST(DataLayoutUpgradeTest, EmptyDataLayout) { EXPECT_EQ(DL2, "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"); // Check that AMDGPU targets add G1 if it's not present. - EXPECT_EQ(UpgradeDataLayoutString("", "r600"), "G1"); + EXPECT_EQ(UpgradeDataLayoutString("", "r600"), "m:e-G1"); EXPECT_EQ( UpgradeDataLayoutString("", "amdgcn"), - "G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32"); + "m:e-G1-ni:7:8:9-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32"); // Check that SPIR & SPIRV targets add G1 if it's not present. EXPECT_EQ(UpgradeDataLayoutString("", "spir"), "G1"); diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp index 7340f56..04cd66c 100644 --- a/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp @@ -420,12 +420,14 @@ TEST(LegalizerInfoTest, RuleSets) { // Raw type form LI.getActionDefinitionsBuilder(G_ADD) - .fewerElementsIf(typeIs(0, v4s32), changeElementCountTo(0, v2s32)) - .fewerElementsIf(typeIs(0, v8s32), changeElementCountTo(0, s32)) - .fewerElementsIf(typeIs(0, LLT::scalable_vector(4, 16)), - changeElementCountTo(0, LLT::scalable_vector(2, 16))) - .fewerElementsIf(typeIs(0, LLT::scalable_vector(8, 16)), - changeElementCountTo(0, s16)); + .fewerElementsIf(typeIs(0, v4s32), + changeElementCountTo(0, ElementCount::getFixed(2))) + .fewerElementsIf(typeIs(0, v8s32), + changeElementCountTo(0, ElementCount::getFixed(1))) + .fewerElementsIf(typeIs(0, LLT::scalable_vector(4, s16)), + changeElementCountTo(0, ElementCount::getScalable(2))) + .fewerElementsIf(typeIs(0, LLT::scalable_vector(8, s16)), + changeElementCountTo(0, ElementCount::getFixed(1))); LegacyInfo.computeTables(); diff --git a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp index 33f53de..d560073 100644 --- a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp +++ b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp @@ -4899,3 +4899,189 @@ TEST(GSYMTest, TestLookupsOfOverlappingAndUnequalRanges) { for (const auto &Line : ExpectedDumpLines) EXPECT_TRUE(DumpStr.find(Line) != std::string::npos); } + +TEST(GSYMTest, TestUnableToLocateDWO) { + // Test that llvm-gsymutil will not produce "uanble to locate DWO file" for + // Apple binaries. Apple uses DW_AT_GNU_dwo_id for non split DWARF purposes + // and this makes llvm-gsymutil create warnings and errors. + // + // 0x0000000b: DW_TAG_compile_unit + // DW_AT_name ("main.cpp") + // DW_AT_language (DW_LANG_C) + // DW_AT_GNU_dwo_id (0xfffffffe) + StringRef yamldata = R"( + debug_str: + - '' + - main.cpp + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_GNU_dwo_id + Form: DW_FORM_data4 + debug_info: + - Length: 0x11 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0xFFFFFFFE + )"; + auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata); + ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded()); + std::unique_ptr<DWARFContext> DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + ASSERT_TRUE(DwarfContext.get() != nullptr); + std::string errors; + raw_string_ostream OS(errors); + OutputAggregator OSAgg(&OS); + GsymCreator GC; + // Make a DWARF transformer that is MachO (Apple) to avoid warnings about + // not finding DWO files. + DwarfTransformer DT(*DwarfContext, GC, /*LDCS=*/false, /*MachO*/ true); + const uint32_t ThreadCount = 1; + ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded()); + ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded()); + + // Make sure this warning is not in the binary + std::string warn("warning: Unable to retrieve DWO .debug_info section for"); + EXPECT_TRUE(errors.find(warn) == std::string::npos); +} + +TEST(GSYMTest, TestDWARFTransformNoErrorForMissingFileDecl) { + // Test that if llvm-gsymutil finds a line table for a compile unit and if + // there are no matching entries for a function in that compile unit, that + // it doesn't print out a error saying that a DIE has an invalid file index + // if there is no DW_AT_decl_file attribute. + // + // 0x0000000b: DW_TAG_compile_unit + // DW_AT_name ("main.cpp") + // DW_AT_language (DW_LANG_C) + // DW_AT_stmt_list (0x00000000) + // + // 0x00000015: DW_TAG_subprogram + // DW_AT_name ("foo") + // DW_AT_low_pc (0x0000000000001000) + // DW_AT_high_pc (0x0000000000001050) + // + // 0x0000002a: NULL + // + // Line table that has entries, but none that match "foo": + // + // Address Line Column File ISA Discriminator OpIndex Flags + // ------------------ ------ ------ ------ --- ------------- ------- ----- + // 0x0000000000002000 10 0 1 0 0 0 is_stmt + // 0x0000000000002050 13 0 1 0 0 0 is_stmt + + StringRef yamldata = R"( + debug_str: + - '' + - main.cpp + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_addr + debug_info: + - Length: 0x27 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0xDEADBEEFDEADBEEF + CStr: foo + - Value: 0x1000 + - Value: 0x1050 + - AbbrCode: 0x0 + debug_line: + - Length: 58 + Version: 2 + PrologueLength: 31 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + Files: + - Name: main.cpp + DirIdx: 0 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 8192 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 80 + - Opcode: DW_LNS_advance_line + SData: 3 + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 + )"; + auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata); + ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded()); + std::unique_ptr<DWARFContext> DwarfContext = + DWARFContext::create(*ErrOrSections, 8); + ASSERT_TRUE(DwarfContext.get() != nullptr); + std::string errors; + raw_string_ostream OS(errors); + OutputAggregator OSAgg(&OS); + GsymCreator GC; + DwarfTransformer DT(*DwarfContext, GC); + const uint32_t ThreadCount = 1; + ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded()); + ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded()); + + // Make sure this warning is not in the binary + std::string error_str("error: function DIE at 0x00000015 has an invalid file " + "index 4294967295 in its DW_AT_decl_file attribute"); + EXPECT_TRUE(errors.find(error_str) == std::string::npos); +} diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp index d4b45ea..2c6650d 100644 --- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp @@ -39,8 +39,11 @@ public: return ExecutorAddr::fromPtr(MB.base()); } - Error finalize(tpctypes::FinalizeRequest FR) { + Expected<ExecutorAddr> initialize(tpctypes::FinalizeRequest FR) { + assert(!FR.Segments.empty()); + ExecutorAddr Base = FR.Segments[0].Addr; for (auto &Seg : FR.Segments) { + Base = std::min(Base, Seg.Addr); char *Mem = Seg.Addr.toPtr<char *>(); memcpy(Mem, Seg.Content.data(), Seg.Content.size()); memset(Mem + Seg.Content.size(), 0, Seg.Size - Seg.Content.size()); @@ -52,10 +55,10 @@ public: if ((Seg.RAG.Prot & MemProt::Exec) != MemProt::Exec) sys::Memory::InvalidateInstructionCache(Mem, Seg.Size); } - return Error::success(); + return Base; } - Error deallocate(std::vector<ExecutorAddr> &Bases) { + Error release(std::vector<ExecutorAddr> &Bases) { Error Err = Error::success(); for (auto &Base : Bases) { auto I = Blocks.find(Base.toPtr<void *>()); @@ -86,18 +89,18 @@ CWrapperFunctionResult testReserve(const char *ArgData, size_t ArgSize) { .release(); } -CWrapperFunctionResult testFinalize(const char *ArgData, size_t ArgSize) { - return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>:: +CWrapperFunctionResult testInitialize(const char *ArgData, size_t ArgSize) { + return WrapperFunction< + rt::SPSSimpleExecutorMemoryManagerInitializeSignature>:: handle(ArgData, ArgSize, - makeMethodWrapperHandler(&SimpleAllocator::finalize)) + makeMethodWrapperHandler(&SimpleAllocator::initialize)) .release(); } -CWrapperFunctionResult testDeallocate(const char *ArgData, size_t ArgSize) { - return WrapperFunction< - rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>:: +CWrapperFunctionResult testRelease(const char *ArgData, size_t ArgSize) { + return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerReleaseSignature>:: handle(ArgData, ArgSize, - makeMethodWrapperHandler(&SimpleAllocator::deallocate)) + makeMethodWrapperHandler(&SimpleAllocator::release)) .release(); } @@ -108,8 +111,8 @@ TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) { EPCGenericJITLinkMemoryManager::SymbolAddrs SAs; SAs.Allocator = ExecutorAddr::fromPtr(&SA); SAs.Reserve = ExecutorAddr::fromPtr(&testReserve); - SAs.Finalize = ExecutorAddr::fromPtr(&testFinalize); - SAs.Deallocate = ExecutorAddr::fromPtr(&testDeallocate); + SAs.Initialize = ExecutorAddr::fromPtr(&testInitialize); + SAs.Release = ExecutorAddr::fromPtr(&testRelease); auto MemMgr = std::make_unique<EPCGenericJITLinkMemoryManager>(*SelfEPC, SAs); StringRef Hello = "hello"; diff --git a/llvm/unittests/ExecutionEngine/Orc/ExecutorAddressTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ExecutorAddressTest.cpp index ae9db14..9a37980 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ExecutorAddressTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ExecutorAddressTest.cpp @@ -97,10 +97,16 @@ TEST(ExecutorAddrTest, AddrRanges) { EXPECT_FALSE(R1.contains(A0)); EXPECT_FALSE(R1.contains(A2)); + EXPECT_TRUE(R3.contains(R0)); // True for singleton range at start. + EXPECT_TRUE(R3.contains(R1)); // True for singleton range at end. + EXPECT_FALSE(R3.contains(R2)); // False for non-overlaping singleton range. + EXPECT_FALSE(R3.contains(R4)); // False for overlapping, uncontained range. + EXPECT_FALSE(R1.overlaps(R0)); EXPECT_FALSE(R1.overlaps(R2)); EXPECT_TRUE(R1.overlaps(R3)); EXPECT_TRUE(R1.overlaps(R4)); + EXPECT_TRUE(R3.overlaps(R4)); EXPECT_LE(R0, R0); EXPECT_LT(R0, R1); 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/ReOptimizeLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp index cd10ffe..686d85d 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp @@ -9,6 +9,7 @@ #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" +#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" #include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h" @@ -42,7 +43,7 @@ protected: // COFF-ARM64 is not supported yet auto Triple = JTMB->getTargetTriple(); - if (Triple.isOSBinFormatCOFF() && Triple.isAArch64()) + if (Triple.isOSBinFormatCOFF()) GTEST_SKIP(); // SystemZ is not supported yet. @@ -84,8 +85,11 @@ protected: ES = std::make_unique<ExecutionSession>(std::move(*EPC)); JD = &ES->createBareJITDylib("main"); + ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>( - *ES, std::make_unique<InProcessMemoryManager>(*PageSize)); + *ES, std::make_unique<MapperJITLinkMemoryManager>( + 10 * 1024 * 1024, + std::make_unique<InProcessMemoryMapper>(*PageSize))); DL = std::make_unique<DataLayout>(std::move(*DLOrErr)); auto TM = JTMB->createTargetMachine(); 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/ExecutionEngine/Orc/SimpleExecutorMemoryManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SimpleExecutorMemoryManagerTest.cpp index 6e9b0b2..9c6f19c 100644 --- a/llvm/unittests/ExecutionEngine/Orc/SimpleExecutorMemoryManagerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/SimpleExecutorMemoryManagerTest.cpp @@ -34,12 +34,12 @@ TEST(SimpleExecutorMemoryManagerTest, AllocFinalizeFree) { SimpleExecutorMemoryManager MemMgr; constexpr unsigned AllocSize = 16384; - auto Mem = MemMgr.allocate(AllocSize); + auto Mem = MemMgr.reserve(AllocSize); EXPECT_THAT_ERROR(Mem.takeError(), Succeeded()); std::string HW = "Hello, world!"; - int FinalizeCounter = 0; + int InitializeCounter = 0; int DeallocateCounter = 0; tpctypes::FinalizeRequest FR; @@ -52,27 +52,27 @@ TEST(SimpleExecutorMemoryManagerTest, AllocFinalizeFree) { {/* Finalize: */ cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( ExecutorAddr::fromPtr(incrementWrapper), - ExecutorAddr::fromPtr(&FinalizeCounter))), + ExecutorAddr::fromPtr(&InitializeCounter))), /* Deallocate: */ cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( ExecutorAddr::fromPtr(incrementWrapper), ExecutorAddr::fromPtr(&DeallocateCounter)))}); - EXPECT_EQ(FinalizeCounter, 0); + EXPECT_EQ(InitializeCounter, 0); EXPECT_EQ(DeallocateCounter, 0); - auto FinalizeErr = MemMgr.finalize(FR); - EXPECT_THAT_ERROR(std::move(FinalizeErr), Succeeded()); + auto InitializeErr = MemMgr.initialize(FR); + EXPECT_THAT_EXPECTED(std::move(InitializeErr), Succeeded()); - EXPECT_EQ(FinalizeCounter, 1); + EXPECT_EQ(InitializeCounter, 1); EXPECT_EQ(DeallocateCounter, 0); EXPECT_EQ(HW, std::string(Mem->toPtr<const char *>())); - auto DeallocateErr = MemMgr.deallocate({*Mem}); - EXPECT_THAT_ERROR(std::move(DeallocateErr), Succeeded()); + auto ReleaseErr = MemMgr.release({*Mem}); + EXPECT_THAT_ERROR(std::move(ReleaseErr), Succeeded()); - EXPECT_EQ(FinalizeCounter, 1); + EXPECT_EQ(InitializeCounter, 1); EXPECT_EQ(DeallocateCounter, 1); } diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp index 95c26b1..a8706ce 100644 --- a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp +++ b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp @@ -431,8 +431,8 @@ TEST_F(OpenMPDecompositionTest, Firstprivate3) { std::string Dir0 = stringify(Dec.output[0]); std::string Dir1 = stringify(Dec.output[1]); std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (12), (27) - ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) + ASSERT_EQ(Dir0, "target map(2, , , , , , (x))"); // (12), (27) + ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21) } @@ -574,9 +574,9 @@ TEST_F(OpenMPDecompositionTest, Lastprivate3) { std::string Dir0 = stringify(Dec.output[0]); std::string Dir1 = stringify(Dec.output[1]); std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (21), (27) - ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) - ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) + ASSERT_EQ(Dir0, "target map(2, , , , , , (x))"); // (21), (27) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) + ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) } // SHARED @@ -984,9 +984,9 @@ TEST_F(OpenMPDecompositionTest, Reduction7) { std::string Dir0 = stringify(Dec.output[0]); std::string Dir1 = stringify(Dec.output[1]); std::string Dir2 = stringify(Dec.output[2]); - ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (36), (10) - ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) - ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) + ASSERT_EQ(Dir0, "target map(2, , , , , , (x))"); // (36), (10) + ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) + ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) } // IF diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp index 58a65b9..67fee96 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" @@ -22,6 +23,7 @@ protected: static ConstantFPRange Full; static ConstantFPRange Empty; static ConstantFPRange Finite; + static ConstantFPRange NonNaN; static ConstantFPRange One; static ConstantFPRange PosZero; static ConstantFPRange NegZero; @@ -44,6 +46,8 @@ ConstantFPRange ConstantFPRangeTest::Empty = ConstantFPRange::getEmpty(APFloat::IEEEdouble()); ConstantFPRange ConstantFPRangeTest::Finite = ConstantFPRange::getFinite(APFloat::IEEEdouble()); +ConstantFPRange ConstantFPRangeTest::NonNaN = + ConstantFPRange::getNonNaN(APFloat::IEEEdouble()); ConstantFPRange ConstantFPRangeTest::One = ConstantFPRange(APFloat(1.0)); ConstantFPRange ConstantFPRangeTest::PosZero = ConstantFPRange( APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false)); @@ -79,15 +83,21 @@ static void strictNext(APFloat &V) { V.next(/*nextDown=*/false); } +enum class SparseLevel { + Dense, + SpecialValuesWithAllPowerOfTwos, + SpecialValuesOnly, +}; + template <typename Fn> -static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive, +static void EnumerateConstantFPRangesImpl(Fn TestFn, SparseLevel Level, bool MayBeQNaN, bool MayBeSNaN) { const fltSemantics &Sem = APFloat::Float8E4M3(); APFloat PosInf = APFloat::getInf(Sem, /*Negative=*/false); APFloat NegInf = APFloat::getInf(Sem, /*Negative=*/true); TestFn(ConstantFPRange(PosInf, NegInf, MayBeQNaN, MayBeSNaN)); - if (!Exhaustive) { + if (Level != SparseLevel::Dense) { SmallVector<APFloat, 36> Values; Values.push_back(APFloat::getInf(Sem, /*Negative=*/true)); Values.push_back(APFloat::getLargest(Sem, /*Negative=*/true)); @@ -95,10 +105,13 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive, unsigned Exponents = APFloat::semanticsMaxExponent(Sem) - APFloat::semanticsMinExponent(Sem) + 3; unsigned MantissaBits = APFloat::semanticsPrecision(Sem) - 1; - // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent) - for (unsigned M = Exponents - 2; M != 0; --M) - Values.push_back( - APFloat(Sem, APInt(BitWidth, (M + Exponents) << MantissaBits))); + if (Level == SparseLevel::SpecialValuesWithAllPowerOfTwos) { + // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent) + for (unsigned M = Exponents - 2; M != 0; --M) + Values.push_back( + APFloat(Sem, APInt(BitWidth, (M + Exponents) << MantissaBits))); + } + Values.push_back(APFloat::getSmallestNormalized(Sem, /*Negative=*/true)); Values.push_back(APFloat::getSmallest(Sem, /*Negative=*/true)); Values.push_back(APFloat::getZero(Sem, /*Negative=*/true)); size_t E = Values.size(); @@ -127,26 +140,30 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive, } template <typename Fn> -static void EnumerateConstantFPRanges(Fn TestFn, bool Exhaustive) { - EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false, +static void EnumerateConstantFPRanges(Fn TestFn, SparseLevel Level, + bool IgnoreSNaNs = false) { + EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/false, /*MayBeSNaN=*/false); - EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false, - /*MayBeSNaN=*/true); - EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true, + EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/true, /*MayBeSNaN=*/false); - EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true, + if (IgnoreSNaNs) + return; + EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/false, + /*MayBeSNaN=*/true); + EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/true, /*MayBeSNaN=*/true); } template <typename Fn> static void EnumerateTwoInterestingConstantFPRanges(Fn TestFn, - bool Exhaustive) { + SparseLevel Level) { EnumerateConstantFPRanges( [&](const ConstantFPRange &CR1) { EnumerateConstantFPRanges( - [&](const ConstantFPRange &CR2) { TestFn(CR1, CR2); }, Exhaustive); + [&](const ConstantFPRange &CR2) { TestFn(CR1, CR2); }, Level, + /*IgnoreSNaNs=*/true); }, - Exhaustive); + Level, /*IgnoreSNaNs=*/true); } template <typename Fn> @@ -348,16 +365,25 @@ TEST_F(ConstantFPRangeTest, ExhaustivelyEnumerate) { constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1); unsigned Count = 0; EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; }, - /*Exhaustive=*/true); + SparseLevel::Dense); EXPECT_EQ(Expected, Count); } TEST_F(ConstantFPRangeTest, Enumerate) { - constexpr unsigned NNaNValues = 2 * ((1 << 4) - 2 + 4); + constexpr unsigned NNaNValues = 2 * ((1 << 4) - 2 + 5); constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1); unsigned Count = 0; EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; }, - /*Exhaustive=*/false); + SparseLevel::SpecialValuesWithAllPowerOfTwos); + EXPECT_EQ(Expected, Count); +} + +TEST_F(ConstantFPRangeTest, EnumerateWithSpecialValuesOnly) { + constexpr unsigned NNaNValues = 2 * 5; + constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1); + unsigned Count = 0; + EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; }, + SparseLevel::SpecialValuesOnly); EXPECT_EQ(Expected, Count); } @@ -459,7 +485,7 @@ TEST_F(ConstantFPRangeTest, FPClassify) { EXPECT_EQ(SignBit, CR.getSignBit()) << CR; EXPECT_EQ(Mask, CR.classify()) << CR; }, - /*Exhaustive=*/true); + SparseLevel::Dense); #endif } @@ -560,7 +586,7 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) { << "Suboptimal result for makeAllowedFCmpRegion(" << Pred << ", " << CR << ")"; }, - /*Exhaustive=*/false); + SparseLevel::SpecialValuesWithAllPowerOfTwos); } #endif } @@ -671,7 +697,7 @@ TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) { << ", " << CR << ")"; } }, - /*Exhaustive=*/false); + SparseLevel::SpecialValuesWithAllPowerOfTwos); } #endif } @@ -804,13 +830,13 @@ TEST_F(ConstantFPRangeTest, negate) { } TEST_F(ConstantFPRangeTest, getWithout) { - EXPECT_EQ(Full.getWithoutNaN(), ConstantFPRange::getNonNaN(Sem)); + EXPECT_EQ(Full.getWithoutNaN(), NonNaN); EXPECT_EQ(NaN.getWithoutNaN(), Empty); EXPECT_EQ(NaN.getWithoutInf(), NaN); EXPECT_EQ(PosInf.getWithoutInf(), Empty); EXPECT_EQ(NegInf.getWithoutInf(), Empty); - EXPECT_EQ(ConstantFPRange::getNonNaN(Sem).getWithoutInf(), Finite); + EXPECT_EQ(NonNaN.getWithoutInf(), Finite); EXPECT_EQ(Zero.getWithoutInf(), Zero); EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), APFloat(3.0)) @@ -925,4 +951,294 @@ TEST_F(ConstantFPRangeTest, cast) { /*IgnoreNaNPayload=*/true); } +TEST_F(ConstantFPRangeTest, add) { + EXPECT_EQ(Full.add(Full), NonNaN.unionWith(QNaN)); + EXPECT_EQ(Full.add(Empty), Empty); + EXPECT_EQ(Empty.add(Full), Empty); + EXPECT_EQ(Empty.add(Empty), Empty); + EXPECT_EQ(One.add(One), ConstantFPRange(APFloat(2.0))); + EXPECT_EQ(Some.add(Some), + ConstantFPRange::getNonNaN(APFloat(-6.0), APFloat(6.0))); + EXPECT_EQ(SomePos.add(SomeNeg), + ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(3.0))); + EXPECT_EQ(PosInf.add(PosInf), PosInf); + EXPECT_EQ(NegInf.add(NegInf), NegInf); + EXPECT_EQ(PosInf.add(Finite.unionWith(PosInf)), PosInf); + EXPECT_EQ(NegInf.add(Finite.unionWith(NegInf)), NegInf); + EXPECT_EQ(PosInf.add(Finite.unionWith(NegInf)), PosInf.unionWith(QNaN)); + EXPECT_EQ(NegInf.add(Finite.unionWith(PosInf)), NegInf.unionWith(QNaN)); + EXPECT_EQ(PosInf.add(NegInf), QNaN); + EXPECT_EQ(NegInf.add(PosInf), QNaN); + EXPECT_EQ(PosZero.add(NegZero), PosZero); + EXPECT_EQ(PosZero.add(Zero), PosZero); + EXPECT_EQ(NegZero.add(NegZero), NegZero); + EXPECT_EQ(NegZero.add(Zero), Zero); + EXPECT_EQ(NaN.add(NaN), QNaN); + EXPECT_EQ(NaN.add(Finite), QNaN); + EXPECT_EQ(NonNaN.unionWith(NaN).add(NonNaN), NonNaN.unionWith(QNaN)); + EXPECT_EQ(PosInf.unionWith(QNaN).add(PosInf), PosInf.unionWith(QNaN)); + EXPECT_EQ(PosInf.unionWith(NaN).add(ConstantFPRange(APFloat(24.0))), + PosInf.unionWith(QNaN)); + +#if defined(EXPENSIVE_CHECKS) + EnumerateTwoInterestingConstantFPRanges( + [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) { + ConstantFPRange Res = LHS.add(RHS); + ConstantFPRange Expected = + ConstantFPRange::getEmpty(LHS.getSemantics()); + EnumerateValuesInConstantFPRange( + LHS, + [&](const APFloat &LHSC) { + EnumerateValuesInConstantFPRange( + RHS, + [&](const APFloat &RHSC) { + APFloat Sum = LHSC + RHSC; + EXPECT_TRUE(Res.contains(Sum)) + << "Wrong result for " << LHS << " + " << RHS + << ". The result " << Res << " should contain " << Sum; + if (!Expected.contains(Sum)) + Expected = Expected.unionWith(ConstantFPRange(Sum)); + }, + /*IgnoreNaNPayload=*/true); + }, + /*IgnoreNaNPayload=*/true); + EXPECT_EQ(Res, Expected) + << "Suboptimal result for " << LHS << " + " << RHS << ". Expected " + << Expected << ", but got " << Res; + }, + SparseLevel::SpecialValuesOnly); +#endif +} + +TEST_F(ConstantFPRangeTest, sub) { + EXPECT_EQ(Full.sub(Full), NonNaN.unionWith(QNaN)); + EXPECT_EQ(Full.sub(Empty), Empty); + EXPECT_EQ(Empty.sub(Full), Empty); + EXPECT_EQ(Empty.sub(Empty), Empty); + EXPECT_EQ(One.sub(One), ConstantFPRange(APFloat(0.0))); + EXPECT_EQ(Some.sub(Some), + ConstantFPRange::getNonNaN(APFloat(-6.0), APFloat(6.0))); + EXPECT_EQ(SomePos.sub(SomeNeg), + ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(6.0))); + EXPECT_EQ(PosInf.sub(NegInf), PosInf); + EXPECT_EQ(NegInf.sub(PosInf), NegInf); + EXPECT_EQ(PosInf.sub(Finite.unionWith(NegInf)), PosInf); + EXPECT_EQ(NegInf.sub(Finite.unionWith(PosInf)), NegInf); + EXPECT_EQ(PosInf.sub(Finite.unionWith(PosInf)), PosInf.unionWith(QNaN)); + EXPECT_EQ(NegInf.sub(Finite.unionWith(NegInf)), NegInf.unionWith(QNaN)); + EXPECT_EQ(PosInf.sub(PosInf), QNaN); + EXPECT_EQ(NegInf.sub(NegInf), QNaN); + EXPECT_EQ(PosZero.sub(NegZero), PosZero); + EXPECT_EQ(PosZero.sub(Zero), PosZero); + EXPECT_EQ(NegZero.sub(NegZero), PosZero); + EXPECT_EQ(NegZero.sub(PosZero), NegZero); + EXPECT_EQ(NegZero.sub(Zero), Zero); + EXPECT_EQ(NaN.sub(NaN), QNaN); + EXPECT_EQ(NaN.add(Finite), QNaN); + +#if defined(EXPENSIVE_CHECKS) + EnumerateTwoInterestingConstantFPRanges( + [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) { + ConstantFPRange Res = LHS.sub(RHS); + ConstantFPRange Expected = + ConstantFPRange::getEmpty(LHS.getSemantics()); + EnumerateValuesInConstantFPRange( + LHS, + [&](const APFloat &LHSC) { + EnumerateValuesInConstantFPRange( + RHS, + [&](const APFloat &RHSC) { + APFloat Diff = LHSC - RHSC; + EXPECT_TRUE(Res.contains(Diff)) + << "Wrong result for " << LHS << " - " << RHS + << ". The result " << Res << " should contain " << Diff; + if (!Expected.contains(Diff)) + Expected = Expected.unionWith(ConstantFPRange(Diff)); + }, + /*IgnoreNaNPayload=*/true); + }, + /*IgnoreNaNPayload=*/true); + EXPECT_EQ(Res, Expected) + << "Suboptimal result for " << LHS << " - " << RHS << ". Expected " + << Expected << ", but got " << Res; + }, + SparseLevel::SpecialValuesOnly); +#endif +} + +TEST_F(ConstantFPRangeTest, mul) { + EXPECT_EQ(Full.mul(Full), NonNaN.unionWith(QNaN)); + EXPECT_EQ(Full.mul(Empty), Empty); + EXPECT_EQ(Empty.mul(Full), Empty); + EXPECT_EQ(Empty.mul(Empty), Empty); + EXPECT_EQ(One.mul(One), ConstantFPRange(APFloat(1.0))); + EXPECT_EQ(Some.mul(Some), + ConstantFPRange::getNonNaN(APFloat(-9.0), APFloat(9.0))); + EXPECT_EQ(SomePos.mul(SomeNeg), + ConstantFPRange::getNonNaN(APFloat(-9.0), APFloat(-0.0))); + EXPECT_EQ(PosInf.mul(PosInf), PosInf); + EXPECT_EQ(NegInf.mul(NegInf), PosInf); + EXPECT_EQ(PosInf.mul(Finite), NonNaN.unionWith(QNaN)); + EXPECT_EQ(NegInf.mul(Finite), NonNaN.unionWith(QNaN)); + EXPECT_EQ(PosInf.mul(NegInf), NegInf); + EXPECT_EQ(NegInf.mul(PosInf), NegInf); + EXPECT_EQ(PosZero.mul(NegZero), NegZero); + EXPECT_EQ(PosZero.mul(Zero), Zero); + EXPECT_EQ(NegZero.mul(NegZero), PosZero); + EXPECT_EQ(NegZero.mul(Zero), Zero); + EXPECT_EQ(NaN.mul(NaN), QNaN); + EXPECT_EQ(NaN.mul(Finite), QNaN); + +#if defined(EXPENSIVE_CHECKS) + EnumerateTwoInterestingConstantFPRanges( + [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) { + ConstantFPRange Res = LHS.mul(RHS); + ConstantFPRange Expected = + ConstantFPRange::getEmpty(LHS.getSemantics()); + EnumerateValuesInConstantFPRange( + LHS, + [&](const APFloat &LHSC) { + EnumerateValuesInConstantFPRange( + RHS, + [&](const APFloat &RHSC) { + APFloat Prod = LHSC * RHSC; + EXPECT_TRUE(Res.contains(Prod)) + << "Wrong result for " << LHS << " * " << RHS + << ". The result " << Res << " should contain " << Prod; + if (!Expected.contains(Prod)) + Expected = Expected.unionWith(ConstantFPRange(Prod)); + }, + /*IgnoreNaNPayload=*/true); + }, + /*IgnoreNaNPayload=*/true); + EXPECT_EQ(Res, Expected) + << "Suboptimal result for " << LHS << " * " << RHS << ". Expected " + << Expected << ", but got " << Res; + }, + SparseLevel::SpecialValuesOnly); +#endif +} + +TEST_F(ConstantFPRangeTest, div) { + EXPECT_EQ(Full.div(Full), NonNaN.unionWith(QNaN)); + EXPECT_EQ(Full.div(Empty), Empty); + EXPECT_EQ(Empty.div(Full), Empty); + EXPECT_EQ(Empty.div(Empty), Empty); + EXPECT_EQ(One.div(One), ConstantFPRange(APFloat(1.0))); + EXPECT_EQ(Some.div(Some), NonNaN.unionWith(QNaN)); + EXPECT_EQ(SomePos.div(SomeNeg), + ConstantFPRange(APFloat::getInf(Sem, /*Negative=*/true), + APFloat::getZero(Sem, /*Negative=*/true), + /*MayBeQNaN=*/true, /*MayBeSNaN=*/false)); + EXPECT_EQ(PosInf.div(PosInf), QNaN); + EXPECT_EQ(NegInf.div(NegInf), QNaN); + EXPECT_EQ(PosInf.div(Finite), NonNaN); + EXPECT_EQ(NegInf.div(Finite), NonNaN); + EXPECT_EQ(PosInf.div(NegInf), QNaN); + EXPECT_EQ(NegInf.div(PosInf), QNaN); + EXPECT_EQ(Zero.div(Zero), QNaN); + EXPECT_EQ(SomePos.div(PosInf), PosZero); + EXPECT_EQ(SomeNeg.div(PosInf), NegZero); + EXPECT_EQ(PosInf.div(SomePos), PosInf); + EXPECT_EQ(NegInf.div(SomeNeg), PosInf); + EXPECT_EQ(NegInf.div(Some), NonNaN); + EXPECT_EQ(NaN.div(NaN), QNaN); + EXPECT_EQ(NaN.div(Finite), QNaN); + +#if defined(EXPENSIVE_CHECKS) + EnumerateTwoInterestingConstantFPRanges( + [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) { + ConstantFPRange Res = LHS.div(RHS); + ConstantFPRange Expected = + ConstantFPRange::getEmpty(LHS.getSemantics()); + EnumerateValuesInConstantFPRange( + LHS, + [&](const APFloat &LHSC) { + EnumerateValuesInConstantFPRange( + RHS, + [&](const APFloat &RHSC) { + APFloat Val = LHSC / RHSC; + EXPECT_TRUE(Res.contains(Val)) + << "Wrong result for " << LHS << " / " << RHS + << ". The result " << Res << " should contain " << Val; + if (!Expected.contains(Val)) + Expected = Expected.unionWith(ConstantFPRange(Val)); + }, + /*IgnoreNaNPayload=*/true); + }, + /*IgnoreNaNPayload=*/true); + EXPECT_EQ(Res, Expected) + << "Suboptimal result for " << LHS << " / " << RHS << ". Expected " + << Expected << ", but got " << Res; + }, + SparseLevel::SpecialValuesOnly); +#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/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp index 54c7ddd..6376165 100644 --- a/llvm/unittests/IR/ConstantsTest.cpp +++ b/llvm/unittests/IR/ConstantsTest.cpp @@ -564,13 +564,17 @@ TEST(ConstantsTest, FoldGlobalVariablePtr) { Global->setAlignment(Align(4)); - ConstantInt *TheConstant(ConstantInt::get(IntType, 2)); + ConstantInt *TheConstant = ConstantInt::get(IntType, 2); - Constant *TheConstantExpr(ConstantExpr::getPtrToInt(Global.get(), IntType)); + Constant *PtrToInt = ConstantExpr::getPtrToInt(Global.get(), IntType); + ASSERT_TRUE( + ConstantFoldBinaryInstruction(Instruction::And, PtrToInt, TheConstant) + ->isNullValue()); - ASSERT_TRUE(ConstantFoldBinaryInstruction(Instruction::And, TheConstantExpr, - TheConstant) - ->isNullValue()); + Constant *PtrToAddr = ConstantExpr::getPtrToAddr(Global.get(), IntType); + ASSERT_TRUE( + ConstantFoldBinaryInstruction(Instruction::And, PtrToAddr, TheConstant) + ->isNullValue()); } // Check that containsUndefOrPoisonElement and containsPoisonElement is working 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/IR/RuntimeLibcallsTest.cpp b/llvm/unittests/IR/RuntimeLibcallsTest.cpp index 26cb7e3..8925d2b 100644 --- a/llvm/unittests/IR/RuntimeLibcallsTest.cpp +++ b/llvm/unittests/IR/RuntimeLibcallsTest.cpp @@ -44,9 +44,9 @@ TEST(RuntimeLibcallsTest, LibcallImplByName) { RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("sqrtl"); ASSERT_EQ(size(SquirtleSquad), 3); auto I = SquirtleSquad.begin(); - EXPECT_EQ(*I++, RTLIB::impl_sqrt_f128); - EXPECT_EQ(*I++, RTLIB::impl_sqrt_f80); - EXPECT_EQ(*I++, RTLIB::impl_sqrt_ppcf128); + EXPECT_EQ(*I++, RTLIB::impl_sqrtl_f128); + EXPECT_EQ(*I++, RTLIB::impl_sqrtl_f80); + EXPECT_EQ(*I++, RTLIB::impl_sqrtl_ppcf128); } // Last libcall @@ -54,9 +54,9 @@ TEST(RuntimeLibcallsTest, LibcallImplByName) { auto Truncs = RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("truncl"); ASSERT_EQ(size(Truncs), 3); auto I = Truncs.begin(); - EXPECT_EQ(*I++, RTLIB::impl_trunc_f128); - EXPECT_EQ(*I++, RTLIB::impl_trunc_f80); - EXPECT_EQ(*I++, RTLIB::impl_trunc_ppcf128); + EXPECT_EQ(*I++, RTLIB::impl_truncl_f128); + EXPECT_EQ(*I++, RTLIB::impl_truncl_f80); + EXPECT_EQ(*I++, RTLIB::impl_truncl_ppcf128); } } diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index 17d9f50..d6a3ca5 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -531,7 +531,7 @@ Sections: // Check that we can detect unsupported versions. SmallString<128> UnsupportedVersionYamlString(CommonYamlString); UnsupportedVersionYamlString += R"( - - Version: 4 + - Version: 5 BBRanges: - BaseAddress: 0x11111 BBEntries: @@ -543,7 +543,7 @@ Sections: { SCOPED_TRACE("unsupported version"); DoCheck(UnsupportedVersionYamlString, - "unsupported SHT_LLVM_BB_ADDR_MAP version: 4"); + "unsupported SHT_LLVM_BB_ADDR_MAP version: 5"); } SmallString<128> ZeroBBRangesYamlString(CommonYamlString); @@ -761,14 +761,14 @@ Sections: BBAddrMap E1 = { {{0x11111, - {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}}}}}}; + {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0}}}}}; BBAddrMap E2 = { - {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}, - {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}}}}}}; + {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}, + {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0}}}}}; BBAddrMap E3 = { - {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}}}}}}; + {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0}}}}}; BBAddrMap E4 = { - {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}}}}}}; + {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0}}}}}; std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; @@ -988,6 +988,123 @@ Sections: } } +// Test for the ELFObjectFile::readBBAddrMap API with BBHash. +TEST(ELFObjectFileTest, ReadBBHash) { + StringRef CommonYamlString(R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .llvm_bb_addr_map_1 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 1 + Entries: + - Version: 4 + Feature: 0x60 + BBRanges: + - BaseAddress: 0x11111 + BBEntries: + - ID: 1 + AddressOffset: 0x0 + Size: 0x1 + Metadata: 0x2 + CallsiteEndOffsets: [ 0x1 , 0x1 ] + Hash: 0x1 + - Name: .llvm_bb_addr_map_2 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 1 + Entries: + - Version: 4 + Feature: 0x48 + BBRanges: + - BaseAddress: 0x22222 + BBEntries: + - ID: 2 + AddressOffset: 0x0 + Size: 0x2 + Metadata: 0x4 + Hash: 0x2 + - BaseAddress: 0xFFFFF + BBEntries: + - ID: 15 + AddressOffset: 0xF0 + Size: 0xF1 + Metadata: 0x1F + Hash: 0xF + - Name: .llvm_bb_addr_map_3 + Type: SHT_LLVM_BB_ADDR_MAP + Link: 2 + Entries: + - Version: 4 + Feature: 0x40 + BBRanges: + - BaseAddress: 0x33333 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x3 + Metadata: 0x6 + Hash: 0x3 + - Name: .llvm_bb_addr_map_4 + Type: SHT_LLVM_BB_ADDR_MAP + # Link: 0 (by default, can be overriden) + Entries: + - Version: 4 + Feature: 0x40 + BBRanges: + - BaseAddress: 0x44444 + BBEntries: + - ID: 0 + AddressOffset: 0x0 + Size: 0x4 + Metadata: 0x18 + Hash: 0x4 +)"); + + BBAddrMap E1 = { + {{0x11111, + {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0x1}}}}}; + BBAddrMap E2 = { + {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0x2}}}, + {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0xF}}}}}; + BBAddrMap E3 = { + {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0x3}}}}}; + BBAddrMap E4 = { + {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0x4}}}}}; + + std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; + std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; + std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; + std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; + + auto DoCheckSucceeds = [&](StringRef YamlString, + std::optional<unsigned> TextSectionIndex, + std::vector<BBAddrMap> ExpectedResult) { + SCOPED_TRACE("for TextSectionIndex: " + + (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + + " and object yaml:\n" + YamlString); + SmallString<0> Storage; + Expected<ELFObjectFile<ELF64LE>> ElfOrErr = + toBinary<ELF64LE>(Storage, YamlString); + ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); + + Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = + ElfOrErr->getELFFile().getSection(1); + ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); + auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); + ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); + EXPECT_EQ(*BBAddrMaps, ExpectedResult); + }; + + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, + AllBBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps); + DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps); +} + // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap. TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { StringRef CommonYamlString(R"( @@ -1159,29 +1276,32 @@ Sections: )"); BBAddrMap E1 = { - {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}}}}}}; - PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false, false}}; + {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}, 0}}}}}; + PGOAnalysisMap P1 = { + 892, {}, {true, false, false, false, false, false, false}}; BBAddrMap E2 = { - {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}}; + {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}}; PGOAnalysisMap P2 = {{}, {{BlockFrequency(343), {}}}, - {false, true, false, false, false, false}}; - BBAddrMap E3 = {{{0x33333, - {{0, 0x0, 0x3, {false, true, true, false, false}, {}}, - {1, 0x3, 0x3, {false, false, true, false, false}, {}}, - {2, 0x6, 0x3, {false, false, false, false, false}, {}}}}}}; + {false, true, false, false, false, false, false}}; + BBAddrMap E3 = { + {{0x33333, + {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0}, + {1, 0x3, 0x3, {false, false, true, false, false}, {}, 0}, + {2, 0x6, 0x3, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P3 = {{}, {{{}, {{1, BranchProbability::getRaw(0x1111'1111)}, {2, BranchProbability::getRaw(0xeeee'eeee)}}}, {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, {{}, {}}}, - {false, false, true, false, false, false}}; - BBAddrMap E4 = {{{0x44444, - {{0, 0x0, 0x4, {false, false, false, true, true}, {}}, - {1, 0x4, 0x4, {false, false, false, false, false}, {}}, - {2, 0x8, 0x4, {false, false, false, false, false}, {}}, - {3, 0xc, 0x4, {false, false, false, false, false}, {}}}}}}; + {false, false, true, false, false, false, false}}; + BBAddrMap E4 = { + {{0x44444, + {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0}, + {1, 0x4, 0x4, {false, false, false, false, false}, {}, 0}, + {2, 0x8, 0x4, {false, false, false, false, false}, {}, 0}, + {3, 0xc, 0x4, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P4 = { 1000, {{BlockFrequency(1000), @@ -1193,22 +1313,24 @@ Sections: {3, BranchProbability::getRaw(0xeeee'eeee)}}}, {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, {BlockFrequency(1000), {}}}, - {true, true, true, false, false, false}}; + {true, true, true, false, false, false, false}}; BBAddrMap E5 = { - {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}}; - PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false, false}}; + {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}}; + PGOAnalysisMap P5 = { + {}, {}, {false, false, false, false, false, false, false}}; BBAddrMap E6 = { {{0x66666, - {{0, 0x0, 0x6, {false, true, true, false, false}, {}}, - {1, 0x6, 0x6, {false, false, true, false, false}, {}}}}, - {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}, {}}}}}}; + {{0, 0x0, 0x6, {false, true, true, false, false}, {}, 0}, + {1, 0x6, 0x6, {false, false, true, false, false}, {}, 0}}}, + {0x666661, + {{2, 0x0, 0x6, {false, false, false, false, false}, {}, 0}}}}}; PGOAnalysisMap P6 = {{}, {{{}, {{1, BranchProbability::getRaw(0x2222'2222)}, {2, BranchProbability::getRaw(0xcccc'cccc)}}}, {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}}, {{}, {}}}, - {false, false, true, true, false, false}}; + {false, false, true, true, false, false, false}}; std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6}; std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; diff --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp index f88931b5f..1765e15 100644 --- a/llvm/unittests/Object/ELFTypesTest.cpp +++ b/llvm/unittests/Object/ELFTypesTest.cpp @@ -101,21 +101,22 @@ static_assert( "PGOAnalysisMap should use the same type for basic block ID as BBAddrMap"); TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { - const std::array<BBAddrMap::Features, 11> Decoded = { - {{false, false, false, false, false, false}, - {true, false, false, false, false, false}, - {false, true, false, false, false, false}, - {false, false, true, false, false, false}, - {false, false, false, true, false, false}, - {true, true, false, false, false, false}, - {false, true, true, false, false, false}, - {false, true, true, true, false, false}, - {true, true, true, true, false, false}, - {false, false, false, false, true, false}, - {false, false, false, false, false, true}}}; - const std::array<uint8_t, 11> Encoded = {{0b0000, 0b0001, 0b0010, 0b0100, - 0b1000, 0b0011, 0b0110, 0b1110, - 0b1111, 0b1'0000, 0b10'0000}}; + const std::array<BBAddrMap::Features, 12> Decoded = { + {{false, false, false, false, false, false, false}, + {true, false, false, false, false, false, false}, + {false, true, false, false, false, false, false}, + {false, false, true, false, false, false, false}, + {false, false, false, true, false, false, false}, + {true, true, false, false, false, false, false}, + {false, true, true, false, false, false, false}, + {false, true, true, true, false, false, false}, + {true, true, true, true, false, false, false}, + {false, false, false, false, true, false, false}, + {false, false, false, false, false, true, false}, + {false, false, false, false, false, false, true}}}; + const std::array<uint8_t, 12> Encoded = { + {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111, + 0b1'0000, 0b10'0000, 0b100'0000}}; for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) EXPECT_EQ(Feat.encode(), EncodedVal); for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) { @@ -128,9 +129,9 @@ TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) { const std::array<std::string, 2> Errors = { - "invalid encoding for BBAddrMap::Features: 0x40", + "invalid encoding for BBAddrMap::Features: 0x80", "invalid encoding for BBAddrMap::Features: 0xf0"}; - const std::array<uint8_t, 2> Values = {{0b100'0000, 0b1111'0000}}; + const std::array<uint8_t, 2> Values = {{0b1000'0000, 0b1111'0000}}; for (const auto &[Val, Error] : llvm::zip(Values, Errors)) { EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(), FailedWithMessage(Error)); 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/Support/SourceMgrTest.cpp b/llvm/unittests/Support/SourceMgrTest.cpp index 301b64f..c65f001 100644 --- a/llvm/unittests/Support/SourceMgrTest.cpp +++ b/llvm/unittests/Support/SourceMgrTest.cpp @@ -8,6 +8,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" @@ -506,3 +507,13 @@ TEST_F(SourceMgrTest, PrintWithoutLoc) { Diag.print(nullptr, OS, false, false, false); EXPECT_EQ("message\n", Output); } + +TEST_F(SourceMgrTest, IncludeDirs) { + auto VFS = makeIntrusiveRefCnt<vfs::InMemoryFileSystem>(); + VFS->addFile("include/file", 0, MemoryBuffer::getMemBuffer("contents")); + SM.setVirtualFileSystem(std::move(VFS)); + SM.setIncludeDirs({"include"}); + std::string ResolvedPath; + unsigned NumBuffers = SM.AddIncludeFile("file", SMLoc(), ResolvedPath); + EXPECT_EQ(NumBuffers, 1u); +} diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp index c74d157..809960d 100644 --- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp +++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp @@ -177,6 +177,165 @@ 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, ComputeNumSignBits_ADD) { + SDLoc Loc; + auto IntVT = EVT::getIntegerVT(Context, 8); + auto Nneg1 = DAG->getConstant(0xFF, Loc, IntVT); + auto N0 = DAG->getConstant(0x00, Loc, IntVT); + auto N1 = DAG->getConstant(0x01, Loc, IntVT); + auto N5 = DAG->getConstant(0x05, Loc, IntVT); + auto N8 = DAG->getConstant(0x08, 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::ADD, Loc, IntVT, Nsign3, Nsign1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpRhsEo), 1u); + + // ADD 0 -1 + // N0 = 00000000 + // Nneg1 = 11111111 + auto OpNegZero = DAG->getNode(ISD::ADD, Loc, IntVT, N0, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNegZero), 8u); + + // ADD 1 -1 + // N1 = 00000001 + // Nneg1 = 11111111 + auto OpNegOne = DAG->getNode(ISD::ADD, Loc, IntVT, N1, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNegOne), 8u); + + // ADD 8 -1 + // N8 = 00001000 + // Nneg1 = 11111111 + auto OpSeven = DAG->getNode(ISD::ADD, Loc, IntVT, N8, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpSeven), 5u); + + // Non negative + // Nsign3 = 000????0 + // Nneg1 = 11111111 + auto OpNonNeg = DAG->getNode(ISD::ADD, Loc, IntVT, Nsign3, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNonNeg), 3u); + + // LHS early out + // Nsign1 = 01010101 + // Nsign3 = 000????0 + auto OpLhsEo = DAG->getNode(ISD::ADD, Loc, IntVT, Nsign1, Nsign3); + EXPECT_EQ(DAG->ComputeNumSignBits(OpLhsEo), 1u); + + // Nsign3 = 000????0 + // N5 = 00000101 + auto Op = DAG->getNode(ISD::ADD, Loc, IntVT, Nsign3, N5); + EXPECT_EQ(DAG->ComputeNumSignBits(Op), 2u); +} + +TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_ADDC) { + SDLoc Loc; + auto IntVT = EVT::getIntegerVT(Context, 8); + auto Nneg1 = DAG->getConstant(0xFF, Loc, IntVT); + auto N0 = DAG->getConstant(0x00, Loc, IntVT); + auto N1 = DAG->getConstant(0x01, Loc, IntVT); + auto N5 = DAG->getConstant(0x05, Loc, IntVT); + auto N8 = DAG->getConstant(0x08, 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::ADDC, Loc, IntVT, Nsign3, Nsign1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpRhsEo), 1u); + + // ADD 0 -1 + // N0 = 00000000 + // Nneg1 = 11111111 + auto OpNegZero = DAG->getNode(ISD::ADDC, Loc, IntVT, N0, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNegZero), 8u); + + // ADD 1 -1 + // N1 = 00000001 + // Nneg1 = 11111111 + auto OpNegOne = DAG->getNode(ISD::ADDC, Loc, IntVT, N1, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNegOne), 8u); + + // ADD 8 -1 + // N8 = 00001000 + // Nneg1 = 11111111 + auto OpSeven = DAG->getNode(ISD::ADDC, Loc, IntVT, N8, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpSeven), 4u); + + // Non negative + // Nsign3 = 000????0 + // Nneg1 = 11111111 + auto OpNonNeg = DAG->getNode(ISD::ADDC, Loc, IntVT, Nsign3, Nneg1); + EXPECT_EQ(DAG->ComputeNumSignBits(OpNonNeg), 3u); + + // LHS early out + // Nsign1 = 01010101 + // Nsign3 = 000????0 + auto OpLhsEo = DAG->getNode(ISD::ADDC, Loc, IntVT, Nsign1, Nsign3); + EXPECT_EQ(DAG->ComputeNumSignBits(OpLhsEo), 1u); + + // Nsign3 = 000????0 + // N5 = 00000101 + auto Op = DAG->getNode(ISD::ADDC, 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}); |