diff options
Diffstat (limited to 'backend/unittests')
29 files changed, 286 insertions, 352 deletions
diff --git a/backend/unittests/CodeGen/CoreTypesTest.cpp b/backend/unittests/CodeGen/CoreTypesTest.cpp index b19d6b4..8ad0ce6 100644 --- a/backend/unittests/CodeGen/CoreTypesTest.cpp +++ b/backend/unittests/CodeGen/CoreTypesTest.cpp @@ -5,12 +5,10 @@ #include "rcc/CodeGen/Register.h" #include "rcc/CodeGen/StableID.h" -#include <array> #include <cstdint> #include <iostream> #include <string_view> #include <type_traits> -#include <unordered_set> namespace { @@ -32,126 +30,92 @@ private: }; void testLowLevelTypes(TestContext &Context) { - const rcc::LLT Invalid; - Context.expect(!Invalid.isValid(), "default LLT must be invalid"); - Context.expect(Invalid.toString() == "LLT_invalid", "invalid LLT spelling must be stable"); - - const rcc::LLT Token = rcc::LLT::token(); - Context.expect(Token.isToken(), "token LLT must preserve its kind"); - Context.expect(Token.scalarBitWidth() == 0, "token LLT must have no bit width"); - Context.expect(Token.toString() == "s0", "token LLT must use the MIR token spelling"); - - auto Any = rcc::LLT::makeAnyScalar(3); - auto Integer = rcc::LLT::makeInteger(3); - Context.expect(Any && Integer, "arbitrary positive scalar widths must be accepted"); - if (Any && Integer) { - Context.expect(Any->isAnyScalar(), "bag-of-bits LLT must preserve its kind"); - Context.expect(Integer->isInteger(), "integer LLT must preserve its kind"); - Context.expect(*Any != *Integer, "bag-of-bits and integer LLTs must remain distinct"); - Context.expect(Any->toString() == "s3", "bag-of-bits LLT spelling must include its width"); - Context.expect(Integer->toString() == "i3", "integer LLT spelling must include its width"); + const rcc::LowLevelType Invalid; + Context.expect(!Invalid.isValid(), "default LowLevelType must be invalid"); + Context.expect(Invalid.toString() == "LLT_invalid", + "invalid LowLevelType spelling must be stable"); + + const rcc::LowLevelType Token = rcc::LowLevelType::token(); + Context.expect(Token.isToken(), "token LowLevelType must preserve its kind"); + Context.expect(Token.scalarBitWidth() == 0, "token LowLevelType must have no bit width"); + Context.expect(Token.toString() == "s0", "token LowLevelType must use the MIR token spelling"); + + auto Scalar = rcc::LowLevelType::makeCategoryNeutralScalar(3); + auto SameScalar = rcc::LowLevelType::makeCategoryNeutralScalar(3); + Context.expect(Scalar && SameScalar, "arbitrary positive scalar widths must be accepted"); + if (Scalar && SameScalar) { + Context.expect(Scalar->isCategoryNeutralScalar(), + "scalar LowLevelType must preserve its category-neutral kind"); + Context.expect(*Scalar == *SameScalar, + "equal-width scalars must have one canonical low-level type"); + Context.expect(Scalar->toString() == "s3", + "scalar LowLevelType spelling must include its width"); } - Context.expect(!rcc::LLT::makeInteger(0), "zero-width integer LLT must be rejected"); - Context.expect(!rcc::LLT::makeInteger(std::uint64_t{1} << 16), - "integer LLT wider than the encoding must be rejected"); - - constexpr std::array FloatCases{ - std::pair{rcc::FloatSemantics::IEEEHalf, std::uint32_t{16}}, - std::pair{rcc::FloatSemantics::BFloat, std::uint32_t{16}}, - std::pair{rcc::FloatSemantics::IEEESingle, std::uint32_t{32}}, - std::pair{rcc::FloatSemantics::IEEEDouble, std::uint32_t{64}}, - std::pair{rcc::FloatSemantics::IEEEQuad, std::uint32_t{128}}, - std::pair{rcc::FloatSemantics::PPCDoubleDouble, std::uint32_t{128}}, - std::pair{rcc::FloatSemantics::Float8E5M2, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E5M2FNUZ, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E4M3, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E4M3FN, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E4M3FNUZ, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E4M3B11FNUZ, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float8E3M4, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::FloatTF32, std::uint32_t{19}}, - std::pair{rcc::FloatSemantics::Float8E8M0FNU, std::uint32_t{8}}, - std::pair{rcc::FloatSemantics::Float6E3M2FN, std::uint32_t{6}}, - std::pair{rcc::FloatSemantics::Float6E2M3FN, std::uint32_t{6}}, - std::pair{rcc::FloatSemantics::Float4E2M1FN, std::uint32_t{4}}, - std::pair{rcc::FloatSemantics::X87DoubleExtended, std::uint32_t{80}}, - }; - - std::unordered_set<rcc::LLT> FloatTypes; - for (const auto &[Semantics, BitWidth] : FloatCases) { - auto Type = rcc::LLT::makeFloat(Semantics); - Context.expect(Type.has_value(), "known floating-point semantics must be accepted"); - if (!Type) - continue; - Context.expect(Type->scalarBitWidth() == BitWidth, - "float LLT must preserve its semantics bit width"); - Context.expect(Type->floatSemantics() == Semantics, - "float LLT must preserve exact floating-point semantics"); - FloatTypes.insert(*Type); - } - Context.expect(FloatTypes.size() == FloatCases.size(), - "distinct floating-point semantics must produce distinct LLTs"); - Context.expect(!rcc::LLT::makeFloat(rcc::FloatSemantics::Count), - "unknown floating-point semantics must be rejected"); + Context.expect(!rcc::LowLevelType::makeCategoryNeutralScalar(0), + "zero-width scalar LowLevelType must be rejected"); + Context.expect(!rcc::LowLevelType::makeCategoryNeutralScalar(std::uint64_t{1} << 16), + "scalar LowLevelType wider than the encoding must be rejected"); - auto Pointer = rcc::LLT::makePointer(rcc::LLT::MaxAddressSpace, 64); + auto Pointer = rcc::LowLevelType::makePointer(rcc::LowLevelType::MaxAddressSpace, 64); Context.expect(Pointer.has_value(), "maximum encodable pointer address space must be accepted"); if (Pointer) { - Context.expect(Pointer->isPointer(), "pointer LLT must preserve its kind"); - Context.expect(Pointer->addressSpace() == rcc::LLT::MaxAddressSpace, - "pointer LLT must preserve its address space"); + Context.expect(Pointer->isPointer(), "pointer LowLevelType must preserve its kind"); + Context.expect(Pointer->addressSpace() == rcc::LowLevelType::MaxAddressSpace, + "pointer LowLevelType must preserve its address space"); Context.expect(Pointer->toString() == "p16777215:64", - "pointer LLT spelling must preserve address space and width"); + "pointer LowLevelType spelling must preserve address space and width"); } - Context.expect(!rcc::LLT::makePointer(std::uint64_t{1} << 24, 64), + Context.expect(!rcc::LowLevelType::makePointer(std::uint64_t{1} << 24, 64), "pointer address spaces wider than the encoding must be rejected"); - auto I33 = rcc::LLT::makeInteger(33); + auto I33 = rcc::LowLevelType::makeCategoryNeutralScalar(33); if (!I33) { Context.expect(false, "i33 construction must succeed before vector tests"); return; } - auto FixedVector = rcc::LLT::makeFixedVector(4, *I33); - Context.expect(FixedVector.has_value(), "fixed integer vector LLT must be accepted"); + auto FixedVector = rcc::LowLevelType::makeFixedVector(4, *I33); + Context.expect(FixedVector.has_value(), "fixed integer vector LowLevelType must be accepted"); if (FixedVector) { - Context.expect(FixedVector->isVector(), "fixed vector LLT must preserve vector kind"); + Context.expect(FixedVector->isVector(), "fixed vector LowLevelType must preserve vector kind"); Context.expect(!FixedVector->isScalableVector(), - "fixed vector LLT must not be marked scalable"); + "fixed vector LowLevelType must not be marked scalable"); Context.expect(FixedVector->minimumElementCount() == 4, - "fixed vector LLT must preserve element count"); + "fixed vector LowLevelType must preserve element count"); Context.expect(FixedVector->scalarElementType() == I33, - "fixed vector LLT must preserve its scalar element type"); - Context.expect(FixedVector->toString() == "<4 x i33>", - "fixed vector LLT spelling must be stable"); + "fixed vector LowLevelType must preserve its scalar element type"); + Context.expect(FixedVector->toString() == "<4 x s33>", + "fixed vector LowLevelType spelling must be stable"); } - auto BFloat = rcc::LLT::makeFloat(rcc::FloatSemantics::BFloat); - if (!BFloat) { - Context.expect(false, "bfloat construction must succeed before vector tests"); + auto S16 = rcc::LowLevelType::makeCategoryNeutralScalar(16); + if (!S16) { + Context.expect(false, "s16 construction must succeed before vector tests"); return; } - auto ScalableVector = rcc::LLT::makeScalableVector(1, *BFloat); + auto ScalableVector = rcc::LowLevelType::makeScalableVector(1, *S16); Context.expect(ScalableVector.has_value(), "scalable vector with one minimum lane must work"); if (ScalableVector) { Context.expect(ScalableVector->isScalableVector(), - "scalable vector LLT must preserve scalability"); - Context.expect(ScalableVector->isFloatVector() && !ScalableVector->isFloat(), - "float vectors must not be classified as scalar floats"); - Context.expect(ScalableVector->floatSemantics() == rcc::FloatSemantics::BFloat, - "float vectors must preserve exact floating-point semantics"); - Context.expect(ScalableVector->toString() == "<vscale x 1 x bf16>", - "scalable float vector spelling must preserve exact semantics"); + "scalable vector LowLevelType must preserve scalability"); + Context.expect(ScalableVector->isVectorValue(), + "category-neutral vectors must preserve their value kind"); + Context.expect(ScalableVector->scalarElementType() == S16, + "scalable vectors must preserve their element type"); + Context.expect(ScalableVector->toString() == "<vscale x 1 x s16>", + "scalable vector spelling must preserve its shape"); } - Context.expect(!rcc::LLT::makeFixedVector(1, *I33), "single-lane fixed vectors must be rejected"); - Context.expect(!rcc::LLT::makeScalableVector(0, *I33), + Context.expect(!rcc::LowLevelType::makeFixedVector(1, *I33), + "single-lane fixed vectors must be rejected"); + Context.expect(!rcc::LowLevelType::makeScalableVector(0, *I33), "zero-lane scalable vectors must be rejected"); - Context.expect(!rcc::LLT::makeFixedVector(4, Token), "token vector elements must be rejected"); + Context.expect(!rcc::LowLevelType::makeFixedVector(4, Token), + "token vector elements must be rejected"); if (FixedVector) { - Context.expect(!rcc::LLT::makeFixedVector(4, *FixedVector), - "nested LLT vectors must be rejected"); + Context.expect(!rcc::LowLevelType::makeFixedVector(4, *FixedVector), + "nested LowLevelType vectors must be rejected"); } } diff --git a/backend/unittests/CodeGen/GenericOpcodesTest.cpp b/backend/unittests/CodeGen/GenericOpcodesTest.cpp index 73c1c36..f946c90 100644 --- a/backend/unittests/CodeGen/GenericOpcodesTest.cpp +++ b/backend/unittests/CodeGen/GenericOpcodesTest.cpp @@ -53,7 +53,8 @@ private: return std::move(*Operand); } -[[nodiscard]] rcc::Register createVirtualRegister(rcc::MachineFunction &Function, rcc::LLT Type) { +[[nodiscard]] rcc::Register createVirtualRegister(rcc::MachineFunction &Function, + rcc::LowLevelType Type) { auto Reg = Function.registerInfo().createVirtualRegister(Type); if (!Reg) std::terminate(); @@ -284,16 +285,19 @@ void testShapesAndTypes(TestContext &Context) { if (!Set || !Function) return; - auto I32 = rcc::LLT::makeInteger(32); - auto I64 = rcc::LLT::makeInteger(64); - auto I1 = rcc::LLT::makeInteger(1); - auto S16 = rcc::LLT::makeAnyScalar(16); - auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); - auto P64 = rcc::LLT::makePointer(0, 64); - auto V2I32 = I32 ? rcc::LLT::makeFixedVector(2, *I32) : rcc::Expected<rcc::LLT>{}; - auto V4I32 = I32 ? rcc::LLT::makeFixedVector(4, *I32) : rcc::Expected<rcc::LLT>{}; - auto V2P64 = P64 ? rcc::LLT::makeFixedVector(2, *P64) : rcc::Expected<rcc::LLT>{}; + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto S16 = rcc::LowLevelType::makeCategoryNeutralScalar(16); + auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto P64 = rcc::LowLevelType::makePointer(0, 64); + auto V2I32 = + I32 ? rcc::LowLevelType::makeFixedVector(2, *I32) : rcc::Expected<rcc::LowLevelType>{}; + auto V4I32 = + I32 ? rcc::LowLevelType::makeFixedVector(4, *I32) : rcc::Expected<rcc::LowLevelType>{}; + auto V2P64 = + P64 ? rcc::LowLevelType::makeFixedVector(2, *P64) : rcc::Expected<rcc::LowLevelType>{}; if (!I1 || !I32 || !I64 || !S16 || !F32 || !F64 || !P64 || !V2I32 || !V4I32 || !V2P64) std::terminate(); auto Dst32 = (*Function)->registerInfo().createVirtualRegister(*I32); @@ -324,7 +328,7 @@ void testShapesAndTypes(TestContext &Context) { AddOperands.back() = registerOperand(*Wide, false); Context.expect(!Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_ADD), AddOperands, (*Function)->registerInfo()), - "G_ADD must reject a source from a different LLT equality group"); + "G_ADD must reject a source from a different LowLevelType equality group"); auto ZeroImmediate = rcc::APInt::fromUnsigned(64, 0); std::vector<rcc::MachineOperand> PointerConstant; @@ -483,10 +487,6 @@ void testShapesAndTypes(TestContext &Context) { FloatingLoad, (*Function)->registerInfo()) .has_value(), "G_FPEXTLOAD must accept a scalar floating result and pointer address"); - FloatingLoad[0] = registerOperand(*Wide, true); - Context.expect(!Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_FPEXTLOAD), - FloatingLoad, (*Function)->registerInfo()), - "G_FPEXTLOAD must reject an integer result"); const std::array<std::uint64_t, 1> FloatWords{0}; auto FloatBits = rcc::APFloat::create(rcc::FloatSemantics::IEEESingle, FloatWords); @@ -513,7 +513,7 @@ void testShapesAndTypes(TestContext &Context) { Context.expect(Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_FCONSTANT), FConstantOperands, (*Function)->registerInfo()) .has_value(), - "G_FCONSTANT must accept a bit-width-compatible LLVM scalar LLT"); + "G_FCONSTANT must accept a bit-width-compatible LLVM scalar LowLevelType"); } void testInstructionMemorySemantics(TestContext &Context) { @@ -524,12 +524,12 @@ void testInstructionMemorySemantics(TestContext &Context) { if (!Set || !Function) return; - const rcc::LLT I1 = *rcc::LLT::makeInteger(1); - const rcc::LLT I32 = *rcc::LLT::makeInteger(32); - const rcc::LLT I64 = *rcc::LLT::makeInteger(64); - const rcc::LLT F64 = *rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); - const rcc::LLT P0 = *rcc::LLT::makePointer(0, 64); - const rcc::LLT P1 = *rcc::LLT::makePointer(1, 64); + const rcc::LowLevelType I1 = *rcc::LowLevelType::makeCategoryNeutralScalar(1); + const rcc::LowLevelType I32 = *rcc::LowLevelType::makeCategoryNeutralScalar(32); + const rcc::LowLevelType I64 = *rcc::LowLevelType::makeCategoryNeutralScalar(64); + const rcc::LowLevelType F64 = *rcc::LowLevelType::makeCategoryNeutralScalar(64); + const rcc::LowLevelType P0 = *rcc::LowLevelType::makePointer(0, 64); + const rcc::LowLevelType P1 = *rcc::LowLevelType::makePointer(1, 64); const rcc::Register Dst32 = createVirtualRegister(**Function, I32); const rcc::Register Dst64 = createVirtualRegister(**Function, I64); const rcc::Register Src32 = createVirtualRegister(**Function, I32); @@ -555,7 +555,7 @@ void testInstructionMemorySemantics(TestContext &Context) { createInstruction(**Function, rcc::GenericOpcode::G_LOAD, std::move(OversizedLoadOperands)); addMemOperand(**Function, OversizedLoad, memoryDescription({rcc::MemoryAccessFlag::Load}, 8)); Context.expect(!Set->validateInstruction(OversizedLoad, (*Function)->registerInfo()), - "G_LOAD must reject an MMO larger than its result LLT"); + "G_LOAD must reject an MMO larger than its result LowLevelType"); std::vector<rcc::MachineOperand> WrongAddressSpaceOperands; WrongAddressSpaceOperands.push_back(registerOperand(Dst64, true)); @@ -648,18 +648,6 @@ void testInstructionMemorySemantics(TestContext &Context) { Context.expect(Set->validateInstruction(FloatingAtomic, (*Function)->registerInfo()).has_value(), "floating atomic RMW must accept a scalar floating value and RMW MMO"); - std::vector<rcc::MachineOperand> WrongFloatingAtomicOperands; - WrongFloatingAtomicOperands.push_back(registerOperand(Dst64, true)); - WrongFloatingAtomicOperands.push_back(registerOperand(Address0, false)); - WrongFloatingAtomicOperands.push_back(registerOperand(Src64, false)); - rcc::MachineInstr &WrongFloatingAtomic = createInstruction( - **Function, rcc::GenericOpcode::G_ATOMICRMW_FADD, std::move(WrongFloatingAtomicOperands)); - addMemOperand(**Function, WrongFloatingAtomic, - memoryDescription({rcc::MemoryAccessFlag::Load, rcc::MemoryAccessFlag::Store}, 8, 0, - rcc::AtomicOperation::ReadModifyWrite)); - Context.expect(!Set->validateInstruction(WrongFloatingAtomic, (*Function)->registerInfo()), - "floating atomic RMW must reject integer value registers"); - std::vector<rcc::MachineOperand> PrefetchOperands; PrefetchOperands.push_back(registerOperand(Address0, false)); PrefetchOperands.push_back(rcc::MachineOperand::immediate(0)); diff --git a/backend/unittests/CodeGen/GlobalISel/GISelMITest.h b/backend/unittests/CodeGen/GlobalISel/GISelMITest.h index 5b16535..20e8854 100644 --- a/backend/unittests/CodeGen/GlobalISel/GISelMITest.h +++ b/backend/unittests/CodeGen/GlobalISel/GISelMITest.h @@ -58,8 +58,8 @@ struct FunctionFixture final { [[nodiscard]] inline rcc::Register createRegister(TestContext &Context, rcc::MachineFunction &Function, std::uint32_t Bits) { - auto Type = rcc::LLT::makeInteger(Bits); - Context.expect(Type.has_value(), "integer LLT construction must succeed"); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); + Context.expect(Type.has_value(), "integer LowLevelType construction must succeed"); if (!Type) return {}; auto Reg = Function.registerInfo().createVirtualRegister(*Type); @@ -69,8 +69,8 @@ createRegister(TestContext &Context, rcc::MachineFunction &Function, std::uint32 [[nodiscard]] inline rcc::Register createFloatRegister(TestContext &Context, rcc::MachineFunction &Function) { - auto Type = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); - Context.expect(Type.has_value(), "floating LLT construction must succeed"); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); + Context.expect(Type.has_value(), "floating LowLevelType construction must succeed"); if (!Type) return {}; auto Reg = Function.registerInfo().createVirtualRegister(*Type); diff --git a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp index 30c2b89..6d9fa3c 100644 --- a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp +++ b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp @@ -252,9 +252,9 @@ void testExtendedRV64GCPipeline(TestContext &Context) { "extended pipeline fixture must be complete"); if (!Target || !Fixture.Function || Fixture.Entry == nullptr) return; - auto I1 = rcc::LLT::makeInteger(1); - auto I64 = rcc::LLT::makeInteger(64); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); if (!I1 || !I64 || !Pointer) return; const rcc::Register Left = createRegister(Context, *Fixture.Function, 64); diff --git a/backend/unittests/CodeGen/InstructionDescriptorTest.cpp b/backend/unittests/CodeGen/InstructionDescriptorTest.cpp index 687e723..d263725 100644 --- a/backend/unittests/CodeGen/InstructionDescriptorTest.cpp +++ b/backend/unittests/CodeGen/InstructionDescriptorTest.cpp @@ -197,7 +197,7 @@ void testOperandValidation(TestContext &Context) { if (!Function) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = (*Function)->registerInfo().createVirtualRegister(*I64); auto Source = (*Function)->registerInfo().createVirtualRegister(*I64); Context.expect(Destination && Source, "descriptor test virtual registers must be allocated"); @@ -261,7 +261,7 @@ void testInstructionValidation(TestContext &Context) { if (!InstructionSet || !Function) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = (*Function)->registerInfo().createVirtualRegister(*I64); Context.expect(Reg.has_value(), "instruction validation register must be allocated"); if (!Reg) diff --git a/backend/unittests/CodeGen/LiveTestSupport.h b/backend/unittests/CodeGen/LiveTestSupport.h index 071e572..f6a3566 100644 --- a/backend/unittests/CodeGen/LiveTestSupport.h +++ b/backend/unittests/CodeGen/LiveTestSupport.h @@ -152,7 +152,7 @@ createFunction(std::string Name, std::uint64_t ID, std::size_t BlockCount) { } [[nodiscard]] inline rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function) { - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Type) return std::unexpected(Type.error()); auto Reg = Function.registerInfo().createVirtualRegister(*Type); diff --git a/backend/unittests/CodeGen/MachineAnalysesTest.cpp b/backend/unittests/CodeGen/MachineAnalysesTest.cpp index 997d031..53cd847 100644 --- a/backend/unittests/CodeGen/MachineAnalysesTest.cpp +++ b/backend/unittests/CodeGen/MachineAnalysesTest.cpp @@ -228,8 +228,8 @@ void testMemoryDependence(TestContext &Context, const rcc::TargetDescription &Ta } auto Block = appendBlock(**Function); auto OtherBlock = appendBlock(**Function); - auto I64 = rcc::LLT::makeInteger(64); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); auto Value = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64) : rcc::Expected<rcc::Register>{std::unexpected(I64.error())}; auto Address = Pointer ? (*Function)->registerInfo().createVirtualRegister(*Pointer) @@ -397,7 +397,7 @@ void testCFGUpdaterPHIs(TestContext &Context, const rcc::TargetDescription &Targ return; } - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64) : rcc::Expected<rcc::Register>{std::unexpected(I64.error())}; auto SourceValue = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64) @@ -475,7 +475,7 @@ void testCFGUpdaterFailureAtomicity(TestContext &Context, const rcc::TargetDescr if (!SplitUpdater.addSuccessor(**Source, **Merge, rcc::BranchProbability::one())) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = I64 ? (*SplitFunction)->registerInfo().createVirtualRegister(*I64) : rcc::Expected<rcc::Register>{std::unexpected(I64.error())}; auto Value = I64 ? (*SplitFunction)->registerInfo().createVirtualRegister(*I64) diff --git a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp index e5acc04..82bcce1 100644 --- a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp +++ b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp @@ -305,7 +305,7 @@ struct SourceFixture final { auto HistoricalInstruction = Function.createInstruction(rcc::Opcode::fromValue(NopOpcode)); Context.expect(HistoricalBlock && HistoricalInstruction, "source arena history must be created"); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Tombstone = Function.registerInfo().createVirtualRegister(*Type); Context.expect(Tombstone && Function.registerInfo().eraseVirtualRegister(*Tombstone).has_value(), "source vreg history must contain a tombstone"); diff --git a/backend/unittests/CodeGen/MachineIRBuilderTest.cpp b/backend/unittests/CodeGen/MachineIRBuilderTest.cpp index 44a0e32..17e9874 100644 --- a/backend/unittests/CodeGen/MachineIRBuilderTest.cpp +++ b/backend/unittests/CodeGen/MachineIRBuilderTest.cpp @@ -186,7 +186,7 @@ void testTransactionalBuild(TestContext &Context) { if (Block == nullptr) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = Function->registerInfo().createVirtualRegister(*Type); auto Source = Function->registerInfo().createVirtualRegister(*Type); Context.expect(Destination && Source, "builder virtual registers must be allocated"); @@ -331,7 +331,7 @@ void testImplicitAndMemoryValidation(TestContext &Context) { if (Block == nullptr || OtherBlock == nullptr) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = Function->registerInfo().createVirtualRegister(*Type); auto Source = Function->registerInfo().createVirtualRegister(*Type); Context.expect(Destination && Source, "implicit test virtual registers must be allocated"); @@ -497,7 +497,7 @@ void testStaleCursorsAndOwnedOperands(TestContext &Context) { if (Block == nullptr) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = Function->registerInfo().createVirtualRegister(*Type); auto Source = Function->registerInfo().createVirtualRegister(*Type); if (!Destination || !Source) diff --git a/backend/unittests/CodeGen/MachineIRCoreTest.cpp b/backend/unittests/CodeGen/MachineIRCoreTest.cpp index 6365e59..875eeb8 100644 --- a/backend/unittests/CodeGen/MachineIRCoreTest.cpp +++ b/backend/unittests/CodeGen/MachineIRCoreTest.cpp @@ -116,7 +116,8 @@ void testOperandKinds(TestContext &Context) { Context.expect(!rcc::APFloat::create(rcc::FloatSemantics::IEEEHalf, TooManyHalfWords), "floating immediate word-count mismatch must be rejected"); - auto Virtual = Function->registerInfo().createVirtualRegister(*rcc::LLT::makeInteger(32)); + auto Virtual = Function->registerInfo().createVirtualRegister( + *rcc::LowLevelType::makeCategoryNeutralScalar(32)); Context.expect(Virtual.has_value(), "operand test virtual register must be created"); if (!Virtual) return; @@ -205,7 +206,7 @@ void testRegisterInfoAndOperandMovement(TestContext &Context) { if (Block == nullptr) return; - auto I32 = rcc::LLT::makeInteger(32); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); Context.expect(I32.has_value(), "i32 construction for MRI test must succeed"); if (!I32) return; @@ -317,7 +318,7 @@ void testRegisterInfoAndOperandMovement(TestContext &Context) { Context.expect(V0Info && V0Info->get().Type == I32 && V0Info->get().Bank == rcc::RegisterBankID::fromValue(3) && V0Info->get().RegClass == rcc::RegisterClassID::fromValue(4), - "MRI virtual register properties must evolve without losing LLT"); + "MRI virtual register properties must evolve without losing LowLevelType"); Context.expect(MRI.addLiveIn(*PhysReg, *V0).has_value(), "MRI must record function physical live-ins"); diff --git a/backend/unittests/CodeGen/MachineOptimizationTest.cpp b/backend/unittests/CodeGen/MachineOptimizationTest.cpp index bb2c0e1..cffd4e1 100644 --- a/backend/unittests/CodeGen/MachineOptimizationTest.cpp +++ b/backend/unittests/CodeGen/MachineOptimizationTest.cpp @@ -169,10 +169,10 @@ void setPostRAProperties(rcc::MachineFunction &Function) { } [[nodiscard]] rcc::Register makeGPR(TestContext &Context, rcc::MachineFunction &Function) { - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Type ? Function.registerInfo().createVirtualRegister(*Type) - : rcc::Expected<rcc::Register>(std::unexpected( - rcc::Error(rcc::ErrorCode::InternalError, "test LLT creation failed"))); + : rcc::Expected<rcc::Register>(std::unexpected(rcc::Error( + rcc::ErrorCode::InternalError, "test LowLevelType creation failed"))); Context.expect(Reg.has_value(), "optimization virtual register creation must succeed"); if (!Reg) return {}; diff --git a/backend/unittests/CodeGen/MachineSchedulingTest.cpp b/backend/unittests/CodeGen/MachineSchedulingTest.cpp index 5162fb8..a3d1de9 100644 --- a/backend/unittests/CodeGen/MachineSchedulingTest.cpp +++ b/backend/unittests/CodeGen/MachineSchedulingTest.cpp @@ -178,10 +178,10 @@ makeSchedulingModel(const rcc::TargetSchedulingHooks *Hooks = nullptr) { } [[nodiscard]] rcc::Register makeGPR(TestContext &Context, rcc::MachineFunction &Function) { - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Type ? Function.registerInfo().createVirtualRegister(*Type) - : rcc::Expected<rcc::Register>(std::unexpected( - rcc::Error(rcc::ErrorCode::InternalError, "test LLT creation failed"))); + : rcc::Expected<rcc::Register>(std::unexpected(rcc::Error( + rcc::ErrorCode::InternalError, "test LowLevelType creation failed"))); Context.expect(Reg.has_value(), "scheduler virtual register creation must succeed"); if (!Reg) return {}; diff --git a/backend/unittests/CodeGen/MachineValueTypesTest.cpp b/backend/unittests/CodeGen/MachineValueTypesTest.cpp index 819d6cb..315d56e 100644 --- a/backend/unittests/CodeGen/MachineValueTypesTest.cpp +++ b/backend/unittests/CodeGen/MachineValueTypesTest.cpp @@ -184,9 +184,9 @@ void testMachineMemOperand(TestContext &Context) { "failure ordering stronger than success must be rejected"); auto BadAddressSpace = makeBasicLoadDescription(); - BadAddressSpace.AddressSpace = rcc::LLT::MaxAddressSpace + 1; + BadAddressSpace.AddressSpace = rcc::LowLevelType::MaxAddressSpace + 1; Context.expect(!rcc::MachineMemOperand::create(BadAddressSpace), - "MMO address space wider than LLT encoding must be rejected"); + "MMO address space wider than LowLevelType encoding must be rejected"); auto EmptySymbol = makeBasicLoadDescription(); EmptySymbol.Base = rcc::MemoryBase::externalSymbol(""); diff --git a/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp b/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp index 3eb926d..3cc2b56 100644 --- a/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp +++ b/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp @@ -186,7 +186,7 @@ void testValidTargetFacts(TestContext &Context, const rcc::TargetDescription &Ta if (!Fixture.Function) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); if (!Reg) return; @@ -233,7 +233,7 @@ void testSubRegisterProjection(TestContext &Context, const rcc::TargetDescriptio if (!Fixture.Function) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); if (!Reg) return; @@ -282,7 +282,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context, } { auto Fixture = createFunction(Context, "unknown_bank", 5); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Fixture.Function || !Type) return; auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); @@ -295,7 +295,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context, } { auto Fixture = createFunction(Context, "wide_bank_value", 6); - auto Type = rcc::LLT::makeInteger(128); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(128); if (!Fixture.Function || !Type) return; auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); @@ -325,7 +325,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context, } { auto Fixture = createFunction(Context, "bad_allocation_hint", 9); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); Context.expect(Reg && classify(Fixture.Function->registerInfo(), *Reg, @@ -340,7 +340,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context, } { auto Fixture = createFunction(Context, "reserved_allocation_hint", 14); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); const auto G0 = phys(rcc::test::TestRegister::G0); Context.expect(Reg && @@ -355,7 +355,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context, } { auto Fixture = createFunction(Context, "incompatible_function_livein", 15); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type); Context.expect( Reg && @@ -416,7 +416,7 @@ void testRegMaskEarlyClobberAndTies(TestContext &Context, const rcc::TargetDescr } { auto Fixture = createFunction(Context, "incompatible_tie", 12); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto GPR = Fixture.Function->registerInfo().createVirtualRegister(*Type); auto FPR = Fixture.Function->registerInfo().createVirtualRegister(*Type); if (!GPR || !FPR) diff --git a/backend/unittests/CodeGen/MachineVerifierTest.cpp b/backend/unittests/CodeGen/MachineVerifierTest.cpp index c8c512f..5327148 100644 --- a/backend/unittests/CodeGen/MachineVerifierTest.cpp +++ b/backend/unittests/CodeGen/MachineVerifierTest.cpp @@ -196,7 +196,7 @@ buildNoOperand(TestContext &Context, rcc::MachineIRBuilder &Builder, std::uint32 if (Entry == nullptr || Exit == nullptr) return false; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Value = Function.registerInfo().createVirtualRegister(*Type); Context.expect(Value.has_value(), "typed verifier virtual register must be allocated"); if (!Value) @@ -338,7 +338,7 @@ createPhiTestFunction(TestContext &Context, const rcc::TargetDescription &Target return nullptr; } - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Destination = Type ? Function->registerInfo().createVirtualRegister(*Type) : rcc::Expected<rcc::Register>{std::unexpected(Type.error())}; auto LeftValue = Type ? Function->registerInfo().createVirtualRegister(*Type) @@ -411,7 +411,7 @@ void testPropertyFailures(TestContext &Context) { auto Target = createTarget(); if (!Target) return; - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto SSA = createFunction(Context, "ssa", 6); rcc::MachineBasicBlock *SSABlock = SSA ? createBlock(Context, *SSA) : nullptr; @@ -503,7 +503,7 @@ void testPropertyFailures(TestContext &Context) { void testSelectedStateAndPseudoDeadline(TestContext &Context) { auto Target = createTarget(); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Target) return; diff --git a/backend/unittests/CodeGen/PHIEliminationTest.cpp b/backend/unittests/CodeGen/PHIEliminationTest.cpp index 9bc9a57..bbc834f 100644 --- a/backend/unittests/CodeGen/PHIEliminationTest.cpp +++ b/backend/unittests/CodeGen/PHIEliminationTest.cpp @@ -90,7 +90,7 @@ void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescrip auto Fixture = createFunction(Context, "parallel_phis", 1, 3); if (!Fixture.Function || Fixture.Blocks.size() != 3) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!I64) return; auto &Function = *Fixture.Function; @@ -209,7 +209,7 @@ void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescrip Context.expect(FreshInfo.has_value(), "fresh PHI vreg must remain registered"); if (!FreshInfo) return; - Context.expect(FreshInfo->get().Type == I64, "fresh PHI vreg must clone its LLT"); + Context.expect(FreshInfo->get().Type == I64, "fresh PHI vreg must clone its LowLevelType"); Context.expect(FreshInfo->get().Bank == rcc::test::TestRegisterBank::GPR, "fresh PHI vreg must clone its register bank"); Context.expect(FreshInfo->get().RegClass == rcc::test::TestRegisterClass::GPR64, @@ -241,7 +241,7 @@ void testCriticalEdgeAndPhysicalLiveIn(TestContext &Context, const rcc::TargetDe auto Fixture = createFunction(Context, "critical_edge", 2, 4); if (!Fixture.Function || Fixture.Blocks.size() != 4) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!I64) return; auto &Function = *Fixture.Function; @@ -343,7 +343,7 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip auto Fixture = createFunction(Context, "undef_phi", ID, 2); if (!Fixture.Function || Fixture.Blocks.size() != 2) return Fixture; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!I64) return Fixture; auto Source = createVReg(*Fixture.Function, *I64, rcc::test::TestRegisterBank::GPR, @@ -406,9 +406,9 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip } void testMalformedPHIs(TestContext &Context, const rcc::TargetDescription &Target) { - auto BuildBadPhi = [&](std::uint64_t ID, rcc::LLT DestinationType, + auto BuildBadPhi = [&](std::uint64_t ID, rcc::LowLevelType DestinationType, rcc::RegisterBankID DestinationBank, rcc::RegisterClassID DestinationClass, - rcc::LLT SourceType, rcc::RegisterBankID SourceBank, + rcc::LowLevelType SourceType, rcc::RegisterBankID SourceBank, rcc::RegisterClassID SourceClass, rcc::SubRegIndex SourceSubReg = {}) { auto Fixture = createFunction(Context, "bad_phi", ID, 2); if (!Fixture.Function || Fixture.Blocks.size() != 2) @@ -438,8 +438,8 @@ void testMalformedPHIs(TestContext &Context, const rcc::TargetDescription &Targe return Fixture; }; - auto I64 = rcc::LLT::makeInteger(64); - auto I32 = rcc::LLT::makeInteger(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); if (!I64 || !I32) return; auto BadType = diff --git a/backend/unittests/CodeGen/RegisterAllocationTest.cpp b/backend/unittests/CodeGen/RegisterAllocationTest.cpp index 7dd0dd0..443d00a 100644 --- a/backend/unittests/CodeGen/RegisterAllocationTest.cpp +++ b/backend/unittests/CodeGen/RegisterAllocationTest.cpp @@ -352,7 +352,7 @@ struct FunctionFixture final { [[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, rcc::RegisterClassID Class = rcc::test::TestRegisterClass::GPR64) { - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Type) return std::unexpected(Type.error()); auto Reg = Function.registerInfo().createVirtualRegister(*Type); diff --git a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h index d93b14e..7f0a641 100644 --- a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h +++ b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h @@ -201,7 +201,7 @@ struct FunctionFixture final { [[nodiscard]] inline Expected<Register> createVReg(MachineFunction &Function, RegisterClassID Class = TestRegisterClass::GPR64) { - auto Type = LLT::makeInteger(64); + auto Type = LowLevelType::makeCategoryNeutralScalar(64); if (!Type) return std::unexpected(Type.error()); auto Reg = Function.registerInfo().createVirtualRegister(*Type); diff --git a/backend/unittests/CodeGen/SSAExitTestSupport.h b/backend/unittests/CodeGen/SSAExitTestSupport.h index 5729293..cf77d36 100644 --- a/backend/unittests/CodeGen/SSAExitTestSupport.h +++ b/backend/unittests/CodeGen/SSAExitTestSupport.h @@ -360,7 +360,7 @@ struct FunctionFixture final { } [[nodiscard]] inline rcc::Expected<rcc::Register> -createVReg(rcc::MachineFunction &Function, rcc::LLT Type, rcc::RegisterBankID Bank, +createVReg(rcc::MachineFunction &Function, rcc::LowLevelType Type, rcc::RegisterBankID Bank, rcc::RegisterClassID Class, std::uint8_t TargetFlags = 0, std::optional<rcc::PhysicalRegister> Hint = std::nullopt) { auto Reg = Function.registerInfo().createVirtualRegister(Type); diff --git a/backend/unittests/CodeGen/TargetCallLoweringTest.cpp b/backend/unittests/CodeGen/TargetCallLoweringTest.cpp index c5170d0..22a2b0c 100644 --- a/backend/unittests/CodeGen/TargetCallLoweringTest.cpp +++ b/backend/unittests/CodeGen/TargetCallLoweringTest.cpp @@ -42,8 +42,8 @@ private: return *Value; } -[[nodiscard]] rcc::LLT integer(std::uint32_t Bits) { - const auto Type = rcc::LLT::makeInteger(Bits); +[[nodiscard]] rcc::LowLevelType integer(std::uint32_t Bits) { + const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); if (!Type) std::terminate(); return *Type; @@ -207,7 +207,7 @@ void testPlanValidation(TestContext &Context) { auto BadByVal = emptyPlanDescription(rcc::CallLoweringPlanKind::Call); auto ByValAssignment = registerAssignment(); - ByValAssignment.ValueType = *rcc::LLT::makePointer(0, 64); + ByValAssignment.ValueType = *rcc::LowLevelType::makePointer(0, 64); ByValAssignment.LocationType = ByValAssignment.ValueType; ByValAssignment.CustomFlags.set(rcc::CCAssignmentFlag::ByVal); BadByVal.ArgumentAssignments.push_back(ByValAssignment); @@ -219,7 +219,7 @@ void testPlanValidation(TestContext &Context) { auto OverlappingByVal = emptyPlanDescription(rcc::CallLoweringPlanKind::Call); OverlappingByVal.CallFrame.SizeBytes = 32; auto FirstByVal = registerAssignment(); - FirstByVal.ValueType = *rcc::LLT::makePointer(0, 64); + FirstByVal.ValueType = *rcc::LowLevelType::makePointer(0, 64); FirstByVal.LocationType = FirstByVal.ValueType; FirstByVal.CustomFlags.set(rcc::CCAssignmentFlag::ByVal); auto SecondByVal = FirstByVal; diff --git a/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp b/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp index 2c44237..bb9a0fc 100644 --- a/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp +++ b/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp @@ -250,7 +250,7 @@ void testTargetDescriptionConstraints(TestContext &Context) { rcc::test::TestRegisterBank::GPR)); auto Function = rcc::MachineFunction::create("constraints", rcc::MachineFunctionStableID::fromValue(1)); - auto Type = rcc::LLT::makeInteger(64); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!SubclassTarget || !Function || !Type) return; @@ -301,7 +301,7 @@ void testTargetDescriptionConstraints(TestContext &Context) { (*Function)->registerInfo()), "physical register operands must reject nonzero subregister indices"); - auto WideType = rcc::LLT::makeInteger(128); + auto WideType = rcc::LowLevelType::makeCategoryNeutralScalar(128); if (!WideType) return; auto WideReg = (*Function)->registerInfo().createVirtualRegister(*WideType); diff --git a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp index e3ad4eb..d23a2eb 100644 --- a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp +++ b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp @@ -19,8 +19,8 @@ void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::Target auto Fixture = createFunction(Context, "two_address", 5, 1); if (!Fixture.Function || Fixture.Blocks.empty()) return; - auto I64 = rcc::LLT::makeInteger(64); - auto I32 = rcc::LLT::makeInteger(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); if (!I64 || !I32) return; auto &Function = *Fixture.Function; diff --git a/backend/unittests/MIR/MIParserTest.cpp b/backend/unittests/MIR/MIParserTest.cpp index c35dc74..4ed39ae 100644 --- a/backend/unittests/MIR/MIParserTest.cpp +++ b/backend/unittests/MIR/MIParserTest.cpp @@ -265,8 +265,8 @@ bb.1."exit block" (landing-pad, bbsections Cold): Context.expect(Registers.size() == 5 && Registers[0].RegClass == rcc::test::TestRegisterClass::GPR64 && Registers[1].RegClass == rcc::test::TestRegisterClass::GPR64 && - Registers[2].Type == *rcc::LLT::makeAnyScalar(128) && - Registers[3].Type == *rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble) && + Registers[2].Type == *rcc::LowLevelType::makeCategoryNeutralScalar(128) && + Registers[3].Type == *rcc::LowLevelType::makeCategoryNeutralScalar(64) && Registers[4].RegClass == rcc::test::TestRegisterClass::GPR64, "textual virtual registers must map deterministically to classed MachineIR vregs"); @@ -385,7 +385,7 @@ void testAddressSpacePointerWidthResolver(TestContext &Context) { "bb.0:\n %0:_(p1) = TEST_COPY $g0\n", ParserContext, ParserOptions); auto Parsed = Parser.parse(); const auto Registers = Function->registerInfo().virtualRegisters(); - auto ExpectedType = rcc::LLT::makePointer(1, 32); + auto ExpectedType = rcc::LowLevelType::makePointer(1, 32); Context.expect(Parsed.has_value() && ExpectedType.has_value() && Registers.size() == 1 && Registers.front().Type == *ExpectedType, "MI parser must use the address-space-specific pointer-width resolver"); @@ -396,35 +396,6 @@ void testAddressSpacePointerWidthResolver(TestContext &Context) { } } -void testUnserializableLowLevelType(TestContext &Context) { - auto Target = createTarget(); - auto Function = createFunction(Context, 4); - Context.expect(Target.has_value(), "unserializable-type target must be valid"); - if (!Target || !Function) - return; - - rcc::mir::MIParserOptions ParserOptions; - ParserOptions.VerifyAfterParse = false; - rcc::mir::MIParser Parser(*Function, *Target, "unserializable-type.mir", - "bb.0:\n %0:gpr64(f64) = TEST_COPY $g0\n", {}, ParserOptions); - auto Parsed = Parser.parse(); - auto Register = rcc::Register::makeVirtual(0); - auto UnsupportedType = rcc::LLT::makeFloat(rcc::FloatSemantics::Float8E5M2); - Context.expect(Parsed.has_value() && Register.has_value() && UnsupportedType.has_value(), - "unserializable-type test setup must parse a typed virtual register"); - if (!Parsed || !Register || !UnsupportedType) - return; - auto SetType = Function->registerInfo().setType(*Register, *UnsupportedType); - Context.expect(SetType.has_value(), "test setup must assign an extended floating low-level type"); - if (!SetType) - return; - - auto Printed = rcc::mir::printMachineFunctionBody(*Function, *Target); - Context.expect(!Printed && Printed.error().message().find("cannot spell this floating") != - std::string_view::npos, - "printer must reject extended low-level types absent from fixed LLVM MIR grammar"); -} - void expectParseError(TestContext &Context, const rcc::TargetDescription &Target, std::string Body, std::string_view Message); @@ -525,7 +496,7 @@ void testLLVMInlineAsmAndConstantMemorySyntax(TestContext &Context) { const auto *ExtraInfo = InlineAsm->operandAt(1)->getIf<std::int64_t>(); const rcc::MachineInstr *Load = InlineAsm->next(); const rcc::MachineMemOperandDesc &Memory = Load->memOperands().front()->description(); - const auto MemoryType = rcc::LLT::makeAnyScalar(64); + const auto MemoryType = rcc::LowLevelType::makeCategoryNeutralScalar(64); Context.expect(ExtraInfo != nullptr && *ExtraInfo == 13, "inline-asm extra-info names must aggregate into the LLVM bit field"); Context.expect(Memory.Base.kind() == rcc::MemoryBase::Kind::IRConstant && @@ -629,7 +600,6 @@ int main() { TestContext Context; testTwoPassBodyParsing(Context); testAddressSpacePointerWidthResolver(Context); - testUnserializableLowLevelType(Context); testCompatibleRegisterClassAndBankAnnotations(Context); testTypedIntegerTruncation(Context); testLLVMInlineAsmAndConstantMemorySyntax(Context); diff --git a/backend/unittests/MIR/MIRDocumentTest.cpp b/backend/unittests/MIR/MIRDocumentTest.cpp index 7f1dfc3..6d84580 100644 --- a/backend/unittests/MIR/MIRDocumentTest.cpp +++ b/backend/unittests/MIR/MIRDocumentTest.cpp @@ -558,7 +558,7 @@ void testHeterogeneousPointerLayout(TestContext &Context) { } const rcc::MachineFunction *Function = Parsed.document()->unit().function("pointer_layout"); - auto PointerType = rcc::LLT::makePointer(1, 32); + auto PointerType = rcc::LowLevelType::makePointer(1, 32); const rcc::MachineConstantPoolEntry *Constant = Function == nullptr ? nullptr : Function->constantPool().entry(rcc::ConstantPoolIndex::fromValue(0)); @@ -584,7 +584,7 @@ void testHeterogeneousPointerLayout(TestContext &Context) { : OverriddenFunction->constantPool().entry(rcc::ConstantPoolIndex::fromValue(0)); const rcc::MachineConstantPoolEntryDesc *OverriddenConstantDescription = OverriddenConstant == nullptr ? nullptr : OverriddenConstant->description(); - const auto OverriddenPointerType = rcc::LLT::makePointer(1, 64); + const auto OverriddenPointerType = rcc::LowLevelType::makePointer(1, 64); Context.expect(Overridden.succeeded() && OverriddenFunction != nullptr && OverriddenPointerType.has_value() && OverriddenFunction->registerInfo().virtualRegisters().size() == 1 && diff --git a/backend/unittests/Target/RISCVCallLoweringTest.cpp b/backend/unittests/Target/RISCVCallLoweringTest.cpp index eee10ab..738aeb1 100644 --- a/backend/unittests/Target/RISCVCallLoweringTest.cpp +++ b/backend/unittests/Target/RISCVCallLoweringTest.cpp @@ -61,29 +61,30 @@ private: return *Value; } -[[nodiscard]] rcc::LLT integer(std::uint32_t Bits) { - const auto Type = rcc::LLT::makeInteger(Bits); +[[nodiscard]] rcc::LowLevelType integer(std::uint32_t Bits) { + const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); if (!Type) std::terminate(); return *Type; } -[[nodiscard]] rcc::LLT anyScalar(std::uint32_t Bits) { - const auto Type = rcc::LLT::makeAnyScalar(Bits); +[[nodiscard]] rcc::LowLevelType anyScalar(std::uint32_t Bits) { + const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); if (!Type) std::terminate(); return *Type; } -[[nodiscard]] rcc::LLT floating(rcc::FloatSemantics Semantics) { - const auto Type = rcc::LLT::makeFloat(Semantics); +[[nodiscard]] rcc::LowLevelType floating(rcc::FloatSemantics Semantics) { + const std::uint32_t Bits = Semantics == rcc::FloatSemantics::IEEESingle ? 32 : 64; + const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); if (!Type) std::terminate(); return *Type; } -[[nodiscard]] rcc::LLT pointer() { - const auto Type = rcc::LLT::makePointer(0, 64); +[[nodiscard]] rcc::LowLevelType pointer() { + const auto Type = rcc::LowLevelType::makePointer(0, 64); if (!Type) std::terminate(); return *Type; @@ -128,13 +129,16 @@ private: return rcc::Register::fromPhysical(physical(rcc::riscv::PhysicalRegisterID::X5)); } -[[nodiscard]] rcc::ABIValue -abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = planningRegister(), - rcc::ABIExtensionKind Extension = rcc::ABIExtensionKind::None) { +[[nodiscard]] rcc::ABIValue abiValue(rcc::LowLevelType Type, std::uint32_t OriginalValue, + rcc::Register Value = planningRegister(), + rcc::ABIExtensionKind Extension = rcc::ABIExtensionKind::None, + std::optional<rcc::ABIValueCategory> Category = std::nullopt) { const std::uint64_t Size = std::max<std::uint64_t>(1, (Type.scalarBitWidth() + 7U) / 8U); return { .Value = Value, .Type = Type, + .Category = Category.value_or(Type.isPointer() ? rcc::ABIValueCategory::Pointer + : rcc::ABIValueCategory::Integer), .OriginalValue = OriginalValue, .FragmentIndex = 0, .FragmentCount = 1, @@ -147,6 +151,13 @@ abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = plann }; } +[[nodiscard]] rcc::ABIValue floatingABIValue(rcc::FloatSemantics Semantics, + std::uint32_t OriginalValue, + rcc::Register Value = planningRegister()) { + return abiValue(floating(Semantics), OriginalValue, Value, rcc::ABIExtensionKind::None, + rcc::ABIValueCategory::FloatingPoint); +} + [[nodiscard]] std::vector<rcc::ABIValue> integerValues(std::size_t Count) { std::vector<rcc::ABIValue> Values; Values.reserve(Count); @@ -160,7 +171,7 @@ abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = plann Values.reserve(Count); for (std::size_t Index = 0; Index < Count; ++Index) { Values.push_back( - abiValue(floating(rcc::FloatSemantics::IEEEDouble), static_cast<std::uint32_t>(Index))); + floatingABIValue(rcc::FloatSemantics::IEEEDouble, static_cast<std::uint32_t>(Index))); } return Values; } @@ -230,8 +241,8 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { FloatAssignments[16].StackOffsetBytes == 0, "LP64D floating arguments must fall back from fa0-fa7 to a0-a7 and then stack"); - auto Single = callRequest({abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}, 1); - Single.Results = {abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}; + auto Single = callRequest({floatingABIValue(rcc::FloatSemantics::IEEESingle, 0)}, 1); + Single.Results = {floatingABIValue(rcc::FloatSemantics::IEEESingle, 0)}; auto SinglePlan = CallLowering.planCall(Single); Context.expect(SinglePlan && SinglePlan->argumentAssignments().size() == 1 && SinglePlan->returnAssignments().size() == 1 && @@ -241,7 +252,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { physical(rcc::riscv::PhysicalRegisterID::F10_F)), "LP64D f32 arguments and returns must use the FPR32 physical-register view"); - auto FloatFragment = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0); + auto FloatFragment = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0); FloatFragment.FragmentCount = 2; FloatFragment.OriginalAlignment = align(16); auto IntegerFragment = abiValue(integer(64), 0); @@ -265,9 +276,9 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { GenericScalarPlan->returnAssignments()[0].ValueType == anyScalar(64), "LLVM generic scalar LLTs must use integer ABI transport without type loss"); - auto LP64Float = callRequest({abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)}, 1); + auto LP64Float = callRequest({floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0)}, 1); LP64Float.Convention = rcc::riscv::callingConventionID(rcc::riscv::CallingConvention::LP64); - LP64Float.Results = {abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)}; + LP64Float.Results = {floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0)}; auto LP64Plan = CallLowering.planCall(LP64Float); const auto LP64Mask = rcc::riscv::createCallPreservedMask(rcc::riscv::CallingConvention::LP64); Context.expect( @@ -295,8 +306,8 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { } void testVariadicAssignments(TestContext &Context) { - auto FixedFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0); - auto VariableFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1); + auto FixedFloat = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0); + auto VariableFloat = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 1); auto Request = callRequest({FixedFloat, VariableFloat}, 1, true); auto Plan = CallLowering.planCall(Request); Context.expect( @@ -385,8 +396,7 @@ void testSpecialArgumentsAndReturns(TestContext &Context) { rcc::ReturnLoweringRequest Return; Return.Convention = convention(); - Return.Values = {abiValue(integer(64), 0), - abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1)}; + Return.Values = {abiValue(integer(64), 0), floatingABIValue(rcc::FloatSemantics::IEEEDouble, 1)}; auto ReturnPlan = CallLowering.planReturn(Return); Context.expect(ReturnPlan && ReturnPlan->returnAssignments().size() == 2 && isLocation(ReturnPlan->returnAssignments()[0], returnGPR(0)) && @@ -455,7 +465,8 @@ void testTailCalls(TestContext &Context) { return std::move(*Function); } -[[nodiscard]] rcc::Register virtualRegister(rcc::MachineFunction &Function, rcc::LLT Type) { +[[nodiscard]] rcc::Register virtualRegister(rcc::MachineFunction &Function, + rcc::LowLevelType Type) { auto Register = Function.registerInfo().createVirtualRegister(Type); if (!Register) std::terminate(); @@ -500,12 +511,12 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) { if (!Target || !Function || Block == nullptr) return; - const rcc::LLT I64 = integer(64); - const rcc::LLT F64 = floating(rcc::FloatSemantics::IEEEDouble); + const rcc::LowLevelType I64 = integer(64); + const rcc::LowLevelType F64 = floating(rcc::FloatSemantics::IEEEDouble); const rcc::Register Argument = virtualRegister(*Function, I64); const rcc::Register Result = virtualRegister(*Function, F64); auto Request = callRequest({abiValue(I64, 0, Argument)}, 1); - Request.Results = {abiValue(F64, 0, Result)}; + Request.Results = {floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0, Result)}; rcc::MachineIRBuilder Builder(*Function, *Target); Context.expect(Builder.setInsertPoint(*Block).has_value(), diff --git a/backend/unittests/Target/RISCVCodeGenTest.cpp b/backend/unittests/Target/RISCVCodeGenTest.cpp index 1bc3361..7392f3b 100644 --- a/backend/unittests/Target/RISCVCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVCodeGenTest.cpp @@ -66,7 +66,7 @@ struct InstructionFixture final { auto Block = (*Function)->createBasicBlock(); if (!Block || !(*Function)->appendBlock(**Block)) return {}; - auto Type = rcc::LLT::makeInteger(Bits); + auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits); if (!Type) return {}; auto Left = (*Function)->registerInfo().createVirtualRegister(*Type); @@ -87,29 +87,28 @@ struct InstructionFixture final { } [[nodiscard]] bool constrainRegister(rcc::MachineFunction &Function, rcc::Register Reg, - rcc::LLT Type) { - const auto Bank = Type.isFloat() ? rcc::RegisterBankID::fromValue( - static_cast<std::uint32_t>(rcc::riscv::RegisterBank::FPR)) - : rcc::RegisterBankID::fromValue( - static_cast<std::uint32_t>(rcc::riscv::RegisterBank::GPR)); - const auto Class = Type.isFloat() - ? rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>( - Type.scalarBitWidth() == 32 ? rcc::riscv::RegisterClass::FPR32 - : rcc::riscv::RegisterClass::FPR64)) - : rcc::RegisterClassID::fromValue( - static_cast<std::uint32_t>(rcc::riscv::RegisterClass::GPR)); + rcc::LowLevelType Type, bool Floating = false) { + const auto Bank = rcc::RegisterBankID::fromValue(static_cast<std::uint32_t>( + Floating ? rcc::riscv::RegisterBank::FPR : rcc::riscv::RegisterBank::GPR)); + const auto Class = rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>( + Floating ? (Type.scalarBitWidth() == 32 ? rcc::riscv::RegisterClass::FPR32 + : rcc::riscv::RegisterClass::FPR64) + : rcc::riscv::RegisterClass::GPR)); return Function.registerInfo().setRegisterBank(Reg, Bank).has_value() && Function.registerInfo().setRegisterClass(Reg, Class).has_value(); } -[[nodiscard]] bool constrainVirtualRegisters(rcc::MachineFunction &Function) { +[[nodiscard]] bool constrainVirtualRegisters(rcc::MachineFunction &Function, + bool FloatingValues = false) { const auto Registers = Function.registerInfo().virtualRegisters(); for (std::size_t Index = 0; Index < Registers.size(); ++Index) { const rcc::VirtualRegisterInfo &Info = Registers[Index]; if (Info.IsTombstone) continue; auto Reg = rcc::Register::makeVirtual(Index); - if (!Reg || !Info.Type || !constrainRegister(Function, *Reg, *Info.Type)) + if (!Reg || !Info.Type || + !constrainRegister(Function, *Reg, *Info.Type, + FloatingValues && Info.Type->scalarBitWidth() != 1)) return false; } return true; @@ -128,8 +127,10 @@ struct InstructionFixture final { [[nodiscard]] std::unique_ptr<rcc::MachineFunction> createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target, - rcc::GenericOpcode Generic, rcc::LLT DestinationType, rcc::LLT SourceType, - rcc::Register *DestinationOut = nullptr, rcc::Register *SourceOut = nullptr) { + rcc::GenericOpcode Generic, rcc::LowLevelType DestinationType, + rcc::LowLevelType SourceType, bool FloatingDestination = false, + bool FloatingSource = false, rcc::Register *DestinationOut = nullptr, + rcc::Register *SourceOut = nullptr) { auto Function = rcc::MachineFunction::create( "riscv_unary", rcc::MachineFunctionStableID::fromValue(200 + static_cast<std::uint32_t>(Generic))); @@ -143,8 +144,8 @@ createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target, auto Source = (*Function)->registerInfo().createVirtualRegister(SourceType); if (!Destination || !Source) return nullptr; - if (!constrainRegister(**Function, *Destination, DestinationType) || - !constrainRegister(**Function, *Source, SourceType)) + if (!constrainRegister(**Function, *Destination, DestinationType, FloatingDestination) || + !constrainRegister(**Function, *Source, SourceType, FloatingSource)) return nullptr; rcc::MachineIRBuilder Builder(**Function, Target); if (!Builder.setInsertPoint(**Block)) @@ -161,7 +162,7 @@ createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target, [[nodiscard]] std::unique_ptr<rcc::MachineFunction> createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target, - rcc::GenericOpcode Generic, rcc::LLT ValueType, bool Floating, + rcc::GenericOpcode Generic, rcc::LowLevelType ValueType, bool Floating, rcc::IntegerPredicate IntegerCondition, rcc::FloatingPredicate FloatingCondition) { auto Function = rcc::MachineFunction::create( @@ -173,15 +174,15 @@ createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target auto Block = (*Function)->createBasicBlock(); if (!Block || !(*Function)->appendBlock(**Block)) return nullptr; - auto ResultType = rcc::LLT::makeInteger(1); + auto ResultType = rcc::LowLevelType::makeCategoryNeutralScalar(1); if (!ResultType) return nullptr; auto Result = (*Function)->registerInfo().createVirtualRegister(*ResultType); auto Left = (*Function)->registerInfo().createVirtualRegister(ValueType); auto Right = (*Function)->registerInfo().createVirtualRegister(ValueType); if (!Result || !Left || !Right || !constrainRegister(**Function, *Result, *ResultType) || - !constrainRegister(**Function, *Left, ValueType) || - !constrainRegister(**Function, *Right, ValueType)) + !constrainRegister(**Function, *Left, ValueType, Floating) || + !constrainRegister(**Function, *Right, ValueType, Floating)) return nullptr; rcc::MachineIRBuilder Builder(**Function, Target); if (!Builder.setInsertPoint(**Block)) @@ -202,7 +203,7 @@ createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target [[nodiscard]] std::unique_ptr<rcc::MachineFunction> createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Target, - rcc::GenericOpcode Generic, rcc::LLT Type) { + rcc::GenericOpcode Generic, rcc::LowLevelType Type) { auto Function = rcc::MachineFunction::create( "riscv_float_binary", rcc::MachineFunctionStableID::fromValue(700 + static_cast<std::uint32_t>(Generic))); @@ -215,8 +216,9 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta auto Left = (*Function)->registerInfo().createVirtualRegister(Type); auto Right = (*Function)->registerInfo().createVirtualRegister(Type); auto Result = (*Function)->registerInfo().createVirtualRegister(Type); - if (!Left || !Right || !Result || !constrainRegister(**Function, *Left, Type) || - !constrainRegister(**Function, *Right, Type) || !constrainRegister(**Function, *Result, Type)) + if (!Left || !Right || !Result || !constrainRegister(**Function, *Left, Type, true) || + !constrainRegister(**Function, *Right, Type, true) || + !constrainRegister(**Function, *Result, Type, true)) return nullptr; rcc::MachineIRBuilder Builder(**Function, Target); if (!Builder.setInsertPoint(**Block)) @@ -230,7 +232,8 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta [[nodiscard]] std::unique_ptr<rcc::MachineFunction> createRegisterOnlyFunction( TestContext &Context, const rcc::TargetDescription &Target, rcc::GenericOpcode Generic, - std::initializer_list<rcc::LLT> DefinitionTypes, std::initializer_list<rcc::LLT> UseTypes) { + std::initializer_list<rcc::LowLevelType> DefinitionTypes, + std::initializer_list<rcc::LowLevelType> UseTypes, bool FloatingValues = false) { auto Function = rcc::MachineFunction::create( "riscv_register_only", rcc::MachineFunctionStableID::fromValue(1000 + static_cast<std::uint32_t>(Generic))); @@ -246,17 +249,17 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta auto Pending = Builder.buildInstr(rcc::opcode(Generic)); if (!Pending) return nullptr; - for (rcc::LLT Type : DefinitionTypes) { + for (rcc::LowLevelType Type : DefinitionTypes) { auto Reg = (*Function)->registerInfo().createVirtualRegister(Type); if (!Reg || !Pending->addDef(*Reg)) return nullptr; } - for (rcc::LLT Type : UseTypes) { + for (rcc::LowLevelType Type : UseTypes) { auto Reg = (*Function)->registerInfo().createVirtualRegister(Type); if (!Reg || !Pending->addUse(*Reg)) return nullptr; } - if (!Pending->build() || !constrainVirtualRegisters(**Function)) + if (!Pending->build() || !constrainVirtualRegisters(**Function, FloatingValues)) return nullptr; return std::move(*Function); } @@ -304,8 +307,8 @@ void testClassification(TestContext &Context) { Context.expect(FloatBlock.has_value(), "floating constant block creation must succeed"); if (!FloatBlock || !(*FloatFunction)->appendBlock(**FloatBlock)) return; - auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); + auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); Context.expect(F32.has_value() && F64.has_value(), "RV64GC floating constant types must be constructible"); if (!F32 || !F64) @@ -442,8 +445,8 @@ void testNarrowIntegerSelection(TestContext &Context) { "narrow integer selection must satisfy target descriptors"); } - auto I7 = rcc::LLT::makeInteger(7); - auto I24 = rcc::LLT::makeInteger(24); + auto I7 = rcc::LowLevelType::makeCategoryNeutralScalar(7); + auto I24 = rcc::LowLevelType::makeCategoryNeutralScalar(24); if (!I7 || !I24) return; auto Compare = createCompareFunction(Context, *Target, rcc::GenericOpcode::G_ICMP, *I7, false, @@ -494,11 +497,11 @@ void testScalarSelection(TestContext &Context) { if (!Target) return; - auto I32 = rcc::LLT::makeInteger(32); - auto I64 = rcc::LLT::makeInteger(64); - auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); - auto I1 = rcc::LLT::makeInteger(1); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); Context.expect(I32 && I64 && F32 && F64 && I1, "scalar test types must be constructible"); if (!I32 || !I64 || !F32 || !F64 || !I1) return; @@ -546,11 +549,14 @@ void testScalarSelection(TestContext &Context) { } } - auto FPExt = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPEXT, *F64, *F32); - auto FPTrunc = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTRUNC, *F32, *F64); - auto FPToSI = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTOSI, *I64, *F32); - auto SIToFP = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_SITOFP, *F64, *I32); - auto Bitcast = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_BITCAST, *I32, *F32); + auto FPExt = + createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPEXT, *F64, *F32, true, true); + auto FPTrunc = + createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTRUNC, *F32, *F64, true, true); + auto FPToSI = + createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTOSI, *I64, *F32, false, true); + auto SIToFP = + createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_SITOFP, *F64, *I32, true, false); if (FPExt) { auto *Instruction = FPExt->firstBlock()->firstInstruction(); Context.expect((*GISel.Selector).select(*Instruction, *FPExt, *Target).has_value(), @@ -583,14 +589,6 @@ void testScalarSelection(TestContext &Context) { rcc::riscv::InstructionOpcode::FCVT_D_W)), "sitofp must select FCVT.D.W"); } - if (Bitcast) { - auto *Instruction = Bitcast->firstBlock()->firstInstruction(); - Context.expect((*GISel.Selector).select(*Instruction, *Bitcast, *Target).has_value(), - "float-to-integer bitcast must select"); - Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( - rcc::riscv::InstructionOpcode::FMV_X_W)), - "float-to-integer bitcast must select FMV.X.W"); - } } void testComparisonsAndControl(TestContext &Context) { @@ -598,9 +596,9 @@ void testComparisonsAndControl(TestContext &Context) { Context.expect(Target.has_value(), "RV64GC target must be available for comparison selection"); if (!Target) return; - auto I64 = rcc::LLT::makeInteger(64); - auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); if (!I64 || !F32 || !Pointer) return; @@ -739,10 +737,10 @@ void testCompositeScalarSelection(TestContext &Context) { Context.expect(Target.has_value(), "RV64GC target must be available for composite selection"); if (!Target) return; - auto I1 = rcc::LLT::makeInteger(1); - auto I32 = rcc::LLT::makeInteger(32); - auto I64 = rcc::LLT::makeInteger(64); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!I1 || !I32 || !I64 || !F64) return; @@ -757,9 +755,9 @@ void testCompositeScalarSelection(TestContext &Context) { auto IntegerSelect = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_SELECT, {*I64}, {*I1, *I64, *I64}); auto FloatSelect = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_SELECT, - {*F64}, {*I1, *F64, *F64}); + {*F64}, {*I1, *F64, *F64}, true); auto CopySign = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_FCOPYSIGN, - {*F64}, {*F64, *F64}); + {*F64}, {*F64, *F64}, true); const std::array Functions{DivRem.get(), MultiplyHigh.get(), Minimum.get(), Absolute.get(), IntegerSelect.get(), FloatSelect.get(), CopySign.get()}; for (rcc::MachineFunction *Function : Functions) { @@ -805,16 +803,16 @@ void testOverflowSelection(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); if (!Target) return; - auto I1 = rcc::LLT::makeInteger(1); - auto I32 = rcc::LLT::makeInteger(32); - auto I64 = rcc::LLT::makeInteger(64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!I1 || !I32 || !I64) return; const std::array Opcodes{rcc::GenericOpcode::G_UADDO, rcc::GenericOpcode::G_USUBO, rcc::GenericOpcode::G_SADDO, rcc::GenericOpcode::G_SSUBO, rcc::GenericOpcode::G_UMULO, rcc::GenericOpcode::G_SMULO}; for (rcc::GenericOpcode Generic : Opcodes) { - const rcc::LLT Type = Generic == rcc::GenericOpcode::G_UMULO ? *I32 : *I64; + const rcc::LowLevelType Type = Generic == rcc::GenericOpcode::G_UMULO ? *I32 : *I64; auto Function = createRegisterOnlyFunction(Context, *Target, Generic, {Type, *I1}, {Type, Type}); Context.expect(Function != nullptr, "overflow fixture must be complete"); @@ -851,10 +849,10 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { if (!Target || !Function) return; auto Block = (*Function)->createBasicBlock(); - auto I1 = rcc::LLT::makeAnyScalar(1); - auto I8 = rcc::LLT::makeAnyScalar(8); - auto I64 = rcc::LLT::makeAnyScalar(64); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto I8 = rcc::LowLevelType::makeCategoryNeutralScalar(8); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); auto Size = rcc::MemorySize::fixed(1); auto Align = rcc::Alignment::create(1); if (!Block || !(*Function)->appendBlock(**Block) || !I1 || !I8 || !I64 || !Pointer || !Size || @@ -1003,8 +1001,8 @@ void testConstantExtensionPreservesLiveSource(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); auto Function = rcc::MachineFunction::create("riscv_live_constant_extension", rcc::MachineFunctionStableID::fromValue(1300)); - auto I32 = rcc::LLT::makeAnyScalar(32); - auto I64 = rcc::LLT::makeAnyScalar(64); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Target || !Function || !I32 || !I64) return; auto Block = (*Function)->createBasicBlock(); @@ -1048,8 +1046,8 @@ void testConstantExtensionPreservesLiveSource(TestContext &Context) { void testIntegerCompareReusesConstantExtension(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); - auto I32 = rcc::LLT::makeAnyScalar(32); - auto I64 = rcc::LLT::makeAnyScalar(64); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Target || !I32 || !I64) return; auto Function = @@ -1109,9 +1107,9 @@ void testNarrowAnyExtBinaryArtifacts(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); auto Function = rcc::MachineFunction::create("riscv_narrow_binary_artifacts", rcc::MachineFunctionStableID::fromValue(1301)); - auto I1 = rcc::LLT::makeAnyScalar(1); - auto I32 = rcc::LLT::makeAnyScalar(32); - auto I64 = rcc::LLT::makeAnyScalar(64); + auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1); + auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Target || !Function || !I1 || !I32 || !I64) return; auto Block = (*Function)->createBasicBlock(); @@ -1240,8 +1238,8 @@ void testAtomicSelection(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); if (!Target) return; - auto I64 = rcc::LLT::makeInteger(64); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); auto Size = rcc::MemorySize::fixed(8); auto Align = rcc::Alignment::create(8); if (!I64 || !Pointer || !Size || !Align) @@ -1397,8 +1395,8 @@ void testUnsupportedTypes(TestContext &Context) { (*GISel.Selector).canSelect(*WideInteger.Instruction, *WideInteger.Function, *Target); Context.expect(!Selection && Selection.error().code() == rcc::ErrorCode::Unsupported, "i128 arithmetic must produce an Unsupported diagnostic"); - Context.expect(!Selection && Selection.error().message().find("i128") != std::string::npos, - "unsupported type diagnostics must name the rejected LLT"); + Context.expect(!Selection && Selection.error().message().find("s128") != std::string::npos, + "unsupported type diagnostics must name the rejected LowLevelType"); } auto Function = rcc::MachineFunction::create("unsupported_type", rcc::MachineFunctionStableID::fromValue(100)); @@ -1407,7 +1405,7 @@ void testUnsupportedTypes(TestContext &Context) { auto Block = (*Function)->createBasicBlock(); if (!Block || !(*Function)->appendBlock(**Block)) return; - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!F64) return; auto Result = (*Function)->registerInfo().createVirtualRegister(*F64); @@ -1447,7 +1445,7 @@ void testVACopyLegalization(TestContext &Context) { if (!Function) return; auto Block = (*Function)->createBasicBlock(); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); if (!Block || !Pointer || !(*Function)->appendBlock(**Block)) return; auto Destination = (*Function)->registerInfo().createVirtualRegister(*Pointer); @@ -1522,8 +1520,8 @@ void testVAArgLegalization(TestContext &Context) { if (!Function) return; auto Block = (*Function)->createBasicBlock(); - auto Pointer = rcc::LLT::makePointer(0, 64); - auto I64 = rcc::LLT::makeInteger(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Block || !Pointer || !I64 || !(*Function)->appendBlock(**Block)) return; auto Destination = (*Function)->registerInfo().createVirtualRegister(*I64); @@ -1611,8 +1609,8 @@ void testFrameIndexLegalization(TestContext &Context) { if (!Function) return; auto Block = (*Function)->createBasicBlock(); - auto Pointer = rcc::LLT::makePointer(0, 64); - auto OtherAddressSpace = rcc::LLT::makePointer(1, 64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); + auto OtherAddressSpace = rcc::LowLevelType::makePointer(1, 64); rcc::StackObjectDesc StackSlot; StackSlot.Size = 8; StackSlot.Align = *rcc::Alignment::create(8); @@ -1653,9 +1651,9 @@ void testPointerArithmeticLegalization(TestContext &Context) { Context.expect(Target.has_value(), "RV64GC target must be available for pointer legalization"); if (!Target) return; - auto Pointer = rcc::LLT::makePointer(0, 64); - auto S64 = rcc::LLT::makeAnyScalar(64); - auto S32 = rcc::LLT::makeAnyScalar(32); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); + auto S64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto S32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); if (!Pointer || !S64 || !S32) return; auto Legal = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_PTR_ADD, @@ -1686,8 +1684,8 @@ void testMemoryOffsetSelection(TestContext &Context) { auto Block = (*Function)->createBasicBlock(); if (!Block || !(*Function)->appendBlock(**Block)) return; - auto I64 = rcc::LLT::makeInteger(64); - auto Pointer = rcc::LLT::makePointer(0, 64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto Pointer = rcc::LowLevelType::makePointer(0, 64); if (!I64 || !Pointer) return; auto Result = (*Function)->registerInfo().createVirtualRegister(*I64); diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp index 89da994..0deebc6 100644 --- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp @@ -727,7 +727,7 @@ void testRISCVMemoryFoldingBoundary(TestContext &Context, const rcc::TargetDescr if (!Function) return; rcc::MachineBasicBlock *Block = appendBlock(Context, *Function); - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto Align = rcc::Alignment::create(8); if (Block == nullptr || !I64 || !Align) return; @@ -995,8 +995,8 @@ void testPseudoPreparation(TestContext &Context, const rcc::TargetDescription &T if (!Function) return; rcc::MachineBasicBlock *Block = appendBlock(Context, *Function); - auto I64 = rcc::LLT::makeInteger(64); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (Block == nullptr || !I64 || !F64) return; auto Source = Function->registerInfo().createVirtualRegister(*I64); diff --git a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp index 6daf58a..29bc756 100644 --- a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp +++ b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp @@ -84,7 +84,8 @@ struct FunctionFixture final { return FunctionFixture{std::move(*Function), *Block}; } -[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, rcc::LLT Type, +[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, + rcc::LowLevelType Type, rcc::riscv::RegisterBank Bank, rcc::riscv::RegisterClass Class) { auto Reg = Function.registerInfo().createVirtualRegister(Type); @@ -304,7 +305,7 @@ void testTargetHooks(TestContext &Context, const rcc::TargetDescription &Target) void testRematerialization(TestContext &Context, const rcc::TargetDescription &Target) { auto Fixture = createFunction("riscv-rematerialization", 2); - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Fixture || !I64) return; auto Original = createVReg(*Fixture->Function, *I64, rcc::riscv::RegisterBank::GPR, @@ -335,7 +336,7 @@ void testRematerialization(TestContext &Context, const rcc::TargetDescription &T [[nodiscard]] rcc::Expected<FunctionFixture> createSimpleAllocationFunction(const rcc::TargetDescription &Target, std::uint64_t ID) { auto Fixture = createFunction("riscv-ra-" + std::to_string(ID), ID); - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Fixture) return std::unexpected(Fixture.error()); if (!I64) @@ -448,7 +449,7 @@ void testFunctionReservedRegisters(TestContext &Context, const rcc::TargetDescri [[nodiscard]] rcc::Expected<FunctionFixture> createPressureFunction(const rcc::TargetDescription &Target, std::uint64_t ID) { auto Fixture = createFunction("riscv-pressure-" + std::to_string(ID), ID); - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); if (!Fixture) return std::unexpected(Fixture.error()); if (!I64) diff --git a/backend/unittests/Target/RISCVSSAExitTest.cpp b/backend/unittests/Target/RISCVSSAExitTest.cpp index 54a5911..1912666 100644 --- a/backend/unittests/Target/RISCVSSAExitTest.cpp +++ b/backend/unittests/Target/RISCVSSAExitTest.cpp @@ -54,7 +54,8 @@ private: return rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>(Class)); } -[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, rcc::LLT Type, +[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, + rcc::LowLevelType Type, rcc::riscv::RegisterBank Bank, rcc::riscv::RegisterClass Class) { auto Reg = Function.registerInfo().createVirtualRegister(Type); @@ -219,9 +220,9 @@ void testBehaviorAndCopyLegality(TestContext &Context, const rcc::TargetDescript Context.expect(Rewritten && *Rewritten && blockOperand(*Jump, 1)->Block == *Third, "RV64GC branch target rewriting must update direct JAL operands"); - auto I64 = rcc::LLT::makeInteger(64); - auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble); - auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); + auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32); if (!I64 || !F64 || !F32) return; auto GPR = @@ -318,7 +319,7 @@ void testRV64GCCriticalEdge(TestContext &Context, const rcc::TargetDescription & auto Merge = appendBlock(**Function); if (!From || !Side || !Other || !Merge) return; - auto I64 = rcc::LLT::makeInteger(64); + auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64); auto X0 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X0); if (!I64 || !X0) return; |
