diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-13 23:55:38 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-13 23:55:38 +0800 |
| commit | aa69e15c6909c3b162b15f5326f0a72ba9bb7163 (patch) | |
| tree | 6428eb20e41bad1fc8ad2f5c259bc5537f54554d /backend/lib/CodeGen | |
| parent | cd30fb546e389d1fb78ce8e579b3dba3a8fdb52a (diff) | |
| download | rcc-project-aa69e15c6909c3b162b15f5326f0a72ba9bb7163.tar.gz rcc-project-aa69e15c6909c3b162b15f5326f0a72ba9bb7163.tar.xz | |
[CodeGen] Unify scalar low-level types
Diffstat (limited to 'backend/lib/CodeGen')
| -rw-r--r-- | backend/lib/CodeGen/GenericOpcodes.cpp | 191 | ||||
| -rw-r--r-- | backend/lib/CodeGen/InstructionDescriptor.cpp | 24 | ||||
| -rw-r--r-- | backend/lib/CodeGen/LowLevelType.cpp | 124 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MIRParser/MIParser.cpp | 70 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MIRPrinter.cpp | 50 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineCSE.cpp | 23 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineLICM.cpp | 11 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineMemOperand.cpp | 2 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineRegisterInfo.cpp | 10 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineSink.cpp | 11 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachineVerifier.cpp | 4 | ||||
| -rw-r--r-- | backend/lib/CodeGen/TargetDescription.cpp | 2 |
12 files changed, 193 insertions, 329 deletions
diff --git a/backend/lib/CodeGen/GenericOpcodes.cpp b/backend/lib/CodeGen/GenericOpcodes.cpp index 0cfd83f..f3ff5f1 100644 --- a/backend/lib/CodeGen/GenericOpcodes.cpp +++ b/backend/lib/CodeGen/GenericOpcodes.cpp @@ -33,52 +33,50 @@ using GO = GenericOpcode; [[nodiscard]] Expected<void> verifyGenericInstructionSemantics(const MachineInstr &Instruction, const MachineRegisterInfo &RegInfo); -[[nodiscard]] LLTKindSet anyValueKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer, LLT::Kind::Float, - LLT::Kind::Pointer, LLT::Kind::VectorAny, LLT::Kind::VectorInteger, - LLT::Kind::VectorFloat, LLT::Kind::VectorPointer}; +[[nodiscard]] LowLevelTypeKindSet anyValueKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Pointer, + LowLevelType::Kind::Vector, LowLevelType::Kind::VectorPointer}; } -[[nodiscard]] LLTKindSet integerKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer, LLT::Kind::VectorAny, LLT::Kind::VectorInteger}; +[[nodiscard]] LowLevelTypeKindSet integerKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Vector}; } -[[nodiscard]] LLTKindSet integerOrPointerKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer, LLT::Kind::Pointer, - LLT::Kind::VectorAny, LLT::Kind::VectorInteger, LLT::Kind::VectorPointer}; +[[nodiscard]] LowLevelTypeKindSet integerOrPointerKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Pointer, + LowLevelType::Kind::Vector, LowLevelType::Kind::VectorPointer}; } -[[nodiscard]] LLTKindSet scalarIntegerKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer}; +[[nodiscard]] LowLevelTypeKindSet scalarIntegerKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar}; } -[[nodiscard]] LLTKindSet scalarIntegerOrPointerKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer, LLT::Kind::Pointer}; +[[nodiscard]] LowLevelTypeKindSet scalarIntegerOrPointerKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Pointer}; } -[[nodiscard]] LLTKindSet scalarValueKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Integer, LLT::Kind::Float, LLT::Kind::Pointer}; +[[nodiscard]] LowLevelTypeKindSet scalarValueKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Pointer}; } -[[nodiscard]] LLTKindSet floatingKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Float, LLT::Kind::VectorAny, LLT::Kind::VectorFloat}; +[[nodiscard]] LowLevelTypeKindSet floatingKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Vector}; } -[[nodiscard]] LLTKindSet scalarFloatingKinds() { - return {LLT::Kind::AnyScalar, LLT::Kind::Float}; +[[nodiscard]] LowLevelTypeKindSet scalarFloatingKinds() { + return {LowLevelType::Kind::CategoryNeutralScalar}; } -[[nodiscard]] LLTKindSet pointerKinds() { - return {LLT::Kind::Pointer, LLT::Kind::VectorPointer}; +[[nodiscard]] LowLevelTypeKindSet pointerKinds() { + return {LowLevelType::Kind::Pointer, LowLevelType::Kind::VectorPointer}; } -[[nodiscard]] LLTKindSet scalarPointerKinds() { - return {LLT::Kind::Pointer}; +[[nodiscard]] LowLevelTypeKindSet scalarPointerKinds() { + return {LowLevelType::Kind::Pointer}; } -[[nodiscard]] LLTKindSet vectorKinds() { - return {LLT::Kind::VectorAny, LLT::Kind::VectorInteger, LLT::Kind::VectorFloat, - LLT::Kind::VectorPointer}; +[[nodiscard]] LowLevelTypeKindSet vectorKinds() { + return {LowLevelType::Kind::Vector, LowLevelType::Kind::VectorPointer}; } [[nodiscard]] OperandKindSet allOperandKinds() { @@ -106,7 +104,7 @@ using GO = GenericOpcode; MachineOperand::Kind::LaneMask}; } -[[nodiscard]] OperandDescriptor typedRegister(RegisterOperandRole Role, LLTKindSet Kinds, +[[nodiscard]] OperandDescriptor typedRegister(RegisterOperandRole Role, LowLevelTypeKindSet Kinds, std::uint16_t Group) { OperandDescriptor Result; Result.Kinds = {MachineOperand::Kind::Register}; @@ -263,22 +261,22 @@ private: return *Value; } -[[nodiscard]] std::uint64_t minimumBitWidth(LLT Type) noexcept { +[[nodiscard]] std::uint64_t minimumBitWidth(LowLevelType Type) noexcept { const std::uint64_t Elements = Type.isVector() ? Type.minimumElementCount() : 1; return Elements * Type.scalarBitWidth(); } -[[nodiscard]] std::uint64_t minimumStoreBytes(LLT Type) noexcept { +[[nodiscard]] std::uint64_t minimumStoreBytes(LowLevelType Type) noexcept { return (minimumBitWidth(Type) + 7) / 8; } -[[nodiscard]] LLT scalarElementType(LLT Type) noexcept { +[[nodiscard]] LowLevelType scalarElementType(LowLevelType Type) noexcept { if (const auto Element = Type.scalarElementType()) return *Element; return Type; } -[[nodiscard]] bool hasSameShape(LLT Left, LLT Right) noexcept { +[[nodiscard]] bool hasSameShape(LowLevelType Left, LowLevelType Right) noexcept { if (Left.isVector() != Right.isVector()) return false; if (!Left.isVector()) @@ -287,18 +285,18 @@ private: Left.minimumElementCount() == Right.minimumElementCount(); } -[[nodiscard]] Expected<void> requireSameShape(LLT Left, LLT Right, std::string_view Message) { +[[nodiscard]] Expected<void> requireSameShape(LowLevelType Left, LowLevelType Right, + std::string_view Message) { if (!hasSameShape(Left, Right)) return semanticError(Message); return {}; } -[[nodiscard]] Expected<void> requireI1WithShape(LLT Condition, LLT Value, +[[nodiscard]] Expected<void> requireI1WithShape(LowLevelType Condition, LowLevelType Value, bool AllowScalarCondition) { - const bool IsScalarInteger = Condition.isAnyScalar() || Condition.isInteger(); - const bool IsVectorInteger = Condition.isAnyVector() || Condition.isIntegerVector(); - if ((!IsScalarInteger && !IsVectorInteger) || Condition.scalarBitWidth() == 0) - return semanticError("generic condition or status result must use an integer LLT"); + if ((!Condition.isCategoryNeutralScalar() && !Condition.isVectorValue()) || + Condition.scalarBitWidth() == 0) + return semanticError("generic condition or status result must use an integer LowLevelType"); if (AllowScalarCondition && !Condition.isVector()) return {}; return requireSameShape(Condition, Value, @@ -308,7 +306,7 @@ private: [[nodiscard]] Expected<void> verifyGenericExplicitOperands(Opcode InstructionOpcode, std::span<const MachineOperand> Operands, const MachineRegisterInfo &RegInfo) { - std::vector<std::optional<LLT>> Types(Operands.size()); + std::vector<std::optional<LowLevelType>> Types(Operands.size()); bool SawNonDefinition = false; for (std::size_t Index = 0; Index < Operands.size(); ++Index) { const MachineOperand &Operand = Operands[Index]; @@ -334,18 +332,18 @@ private: auto Info = RegInfo.virtualRegisterInfo(*Reg); if (!Info) return std::unexpected(Info.error()); - const std::optional<LLT> &Type = Info->get().Type; + const std::optional<LowLevelType> &Type = Info->get().Type; if (!Type) - return semanticError("generic virtual register is missing its LLT"); + return semanticError("generic virtual register is missing its LowLevelType"); Types[Index] = Type.value(); } - const auto TypeAt = [&Types](std::size_t Index) -> LLT { return *Types[Index]; }; + const auto TypeAt = [&Types](std::size_t Index) -> LowLevelType { return *Types[Index]; }; const GO Generic = static_cast<GO>(InstructionOpcode.value()); const auto VerifyWidthChange = [&](bool IsExtension) -> Expected<void> { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (auto Shape = requireSameShape(Dst, Src, "generic width conversion must preserve vector shape"); !Shape) { @@ -389,7 +387,7 @@ private: case GO::G_CONSTANT: { if (const auto *Payload = Operands[1].getIf<IntegerImmediateOperand>(); Payload != nullptr && Payload->Value.bitWidth() != TypeAt(0).scalarBitWidth()) { - return semanticError("G_CONSTANT integer width must match its destination LLT"); + return semanticError("G_CONSTANT integer width must match its destination LowLevelType"); } return {}; } @@ -397,17 +395,14 @@ private: const auto *Payload = Operands[1].getIf<FloatingImmediateOperand>(); if (Payload == nullptr) return semanticError("G_FCONSTANT requires a floating-point immediate"); - const LLT DestinationType = TypeAt(0); - const std::optional<FloatSemantics> DestinationSemantics = DestinationType.floatSemantics(); - if ((DestinationSemantics && Payload->Bits.semantics() != *DestinationSemantics) || - (!DestinationSemantics && Payload->Bits.bitWidth() != DestinationType.scalarBitWidth())) { - return semanticError("G_FCONSTANT semantics must match its destination LLT"); - } + const LowLevelType DestinationType = TypeAt(0); + if (Payload->Bits.bitWidth() != DestinationType.scalarBitWidth()) + return semanticError("G_FCONSTANT width must match its destination LowLevelType"); return {}; } case GO::G_BITCAST: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (Dst.isPointerOrPointerVector() != Src.isPointerOrPointerVector()) return semanticError("G_BITCAST cannot cross the pointer/non-pointer boundary"); if (minimumBitWidth(Dst) != minimumBitWidth(Src) || @@ -415,7 +410,7 @@ private: return semanticError("G_BITCAST source and destination sizes must match"); } if (Dst == Src) - return semanticError("G_BITCAST must change the LLT"); + return semanticError("G_BITCAST must change the LowLevelType"); return {}; } case GO::G_INTTOPTR: @@ -423,8 +418,8 @@ private: return requireSameShape(TypeAt(0), TypeAt(1), "pointer/integer conversion must preserve vector shape"); case GO::G_ADDRSPACE_CAST: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (auto Shape = requireSameShape(Dst, Src, "G_ADDRSPACE_CAST must preserve vector shape"); !Shape) { return Shape; @@ -527,8 +522,8 @@ private: } case GO::G_UNMERGE_VALUES: { const std::size_t DestinationCount = Operands.size() - 1; - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(DestinationCount); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(DestinationCount); if (minimumBitWidth(Src) != minimumBitWidth(Dst) * DestinationCount) return semanticError("G_UNMERGE_VALUES destination widths do not cover the source"); if (Dst.isVector() && (!Src.isVector() || Dst.isScalableVector() != Src.isScalableVector() || @@ -559,22 +554,23 @@ private: } case GO::G_BUILD_VECTOR: case GO::G_BUILD_VECTOR_TRUNC: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (!Dst.isVector() || Dst.isScalableVector() || Src.isVector()) return semanticError("G_BUILD_VECTOR requires a fixed vector result and scalar sources"); if (Dst.minimumElementCount() != Operands.size() - 1) return semanticError("G_BUILD_VECTOR source count must equal the result lane count"); - const LLT Element = scalarElementType(Dst); + const LowLevelType Element = scalarElementType(Dst); if (Generic == GO::G_BUILD_VECTOR && Element != Src) - return semanticError("G_BUILD_VECTOR source LLT must equal the result element LLT"); + return semanticError( + "G_BUILD_VECTOR source LowLevelType must equal the result element LowLevelType"); if (Generic == GO::G_BUILD_VECTOR_TRUNC && Src.scalarBitWidth() <= Element.scalarBitWidth()) return semanticError("G_BUILD_VECTOR_TRUNC sources must be wider than result elements"); return {}; } case GO::G_CONCAT_VECTORS: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (!Dst.isVector() || !Src.isVector() || Dst.isScalableVector() != Src.isScalableVector() || scalarElementType(Dst) != scalarElementType(Src) || Dst.minimumElementCount() != Src.minimumElementCount() * (Operands.size() - 1)) { @@ -604,8 +600,8 @@ private: case GO::G_INSERT_SUBVECTOR: case GO::G_EXTRACT_SUBVECTOR: { const bool IsInsert = Generic == GO::G_INSERT_SUBVECTOR; - const LLT Outer = TypeAt(IsInsert ? 0 : 1); - const LLT Inner = TypeAt(IsInsert ? 2 : 0); + const LowLevelType Outer = TypeAt(IsInsert ? 0 : 1); + const LowLevelType Inner = TypeAt(IsInsert ? 2 : 0); const auto Index = plainImmediate(Operands[IsInsert ? 3 : 2]); if (!Outer.isVector() || !Inner.isVector() || scalarElementType(Outer) != scalarElementType(Inner) || !Index || *Index < 0) { @@ -626,8 +622,8 @@ private: return {}; } case GO::G_SHUFFLE_VECTOR: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); const auto *Mask = Operands[3].getIf<ShuffleMaskOperand>(); if (!Dst.isVector() || !Src.isVector() || Dst.isScalableVector() || Src.isScalableVector() || scalarElementType(Dst) != scalarElementType(Src) || Mask == nullptr || @@ -644,8 +640,8 @@ private: return {}; } case GO::G_SPLAT_VECTOR: { - const LLT Dst = TypeAt(0); - const LLT Src = TypeAt(1); + const LowLevelType Dst = TypeAt(0); + const LowLevelType Src = TypeAt(1); if (!Dst.isScalableVector() || Src.isVector() || scalarElementType(Dst).scalarBitWidth() > Src.scalarBitWidth()) { return semanticError("G_SPLAT_VECTOR requires a scalable result with no wider elements"); @@ -653,7 +649,7 @@ private: return {}; } case GO::G_STEP_VECTOR: { - const LLT Dst = TypeAt(0); + const LowLevelType Dst = TypeAt(0); const auto *Step = Operands[1].getIf<IntegerImmediateOperand>(); if (!Dst.isScalableVector() || Step == nullptr || Step->Value.isZero() || Step->Value.isNegative() || Step->Value.bitWidth() != Dst.scalarBitWidth()) { @@ -662,15 +658,15 @@ private: return {}; } case GO::G_INSERT_VECTOR_ELT: { - const LLT Vector = TypeAt(0); + const LowLevelType Vector = TypeAt(0); if (scalarElementType(Vector) != TypeAt(2) || TypeAt(3).isVector()) - return semanticError("G_INSERT_VECTOR_ELT element or index LLT is incompatible"); + return semanticError("G_INSERT_VECTOR_ELT element or index LowLevelType is incompatible"); return {}; } case GO::G_EXTRACT_VECTOR_ELT: { - const LLT Vector = TypeAt(1); + const LowLevelType Vector = TypeAt(1); if (scalarElementType(Vector) != TypeAt(0) || TypeAt(2).isVector()) - return semanticError("G_EXTRACT_VECTOR_ELT result or index LLT is incompatible"); + return semanticError("G_EXTRACT_VECTOR_ELT result or index LowLevelType is incompatible"); return {}; } case GO::G_VECTOR_COMPRESS: @@ -699,7 +695,7 @@ private: case GO::G_VECREDUCE_UMIN: if (TypeAt(0).isVector() || !TypeAt(1).isVector() || scalarElementType(TypeAt(1)) != TypeAt(0)) { - return semanticError("vector reduction result must equal the source element LLT"); + return semanticError("vector reduction result must equal the source element LowLevelType"); } return {}; case GO::G_SBFX: @@ -807,7 +803,7 @@ private: const auto MemoryOperands = Instruction.memOperands(); const GO Generic = static_cast<GO>(Instruction.opcode().value()); - const auto TypeAt = [&](std::size_t Index) -> Expected<LLT> { + const auto TypeAt = [&](std::size_t Index) -> Expected<LowLevelType> { if (Index >= Operands.size()) return makeUnexpected(ErrorCode::InternalError, "generic semantic verifier operand index is out of range"); @@ -820,7 +816,7 @@ private: return std::unexpected(Info.error()); if (!Info->get().Type) return makeUnexpected(ErrorCode::InternalError, - "generic semantic verifier found a register without an LLT"); + "generic semantic verifier found a register without an LowLevelType"); return *Info->get().Type; }; @@ -830,7 +826,8 @@ private: if (!Type) return std::unexpected(Type.error()); if (!Type->isPointer() || Type->addressSpace() != Memory.description().AddressSpace) - return semanticError("generic memory address LLT and MMO address space do not match"); + return semanticError( + "generic memory address LowLevelType and MMO address space do not match"); return {}; }; @@ -839,7 +836,7 @@ private: NoLarger, StrictlySmaller, }; - const auto VerifySize = [&](LLT ValueType, const MachineMemOperand &Memory, + const auto VerifySize = [&](LowLevelType ValueType, const MachineMemOperand &Memory, SizeRelation Relation) -> Expected<void> { const MemorySize Size = Memory.description().Size; if (!Size.isKnown()) @@ -853,7 +850,8 @@ private: : (Relation == SizeRelation::NoLarger ? MemoryBytes <= ValueBytes : MemoryBytes < ValueBytes); if (!Valid) - return semanticError("generic memory access size is incompatible with its value LLT"); + return semanticError( + "generic memory access size is incompatible with its value LowLevelType"); return {}; }; @@ -1121,17 +1119,17 @@ void configureCoreOpcodes(DescriptorRegistry &Registry) { } void configureGenericOpcodes(DescriptorRegistry &Registry) { - const LLTKindSet AnyTypes = anyValueKinds(); - const LLTKindSet IntTypes = integerKinds(); - const LLTKindSet IntegerOrPointers = integerOrPointerKinds(); - const LLTKindSet ScalarValues = scalarValueKinds(); - const LLTKindSet ScalarInts = scalarIntegerKinds(); - const LLTKindSet ScalarIntegerOrPointers = scalarIntegerOrPointerKinds(); - const LLTKindSet FloatTypes = floatingKinds(); - const LLTKindSet ScalarFloats = scalarFloatingKinds(); - const LLTKindSet PointerTypes = pointerKinds(); - const LLTKindSet ScalarPointers = scalarPointerKinds(); - const LLTKindSet VectorTypes = vectorKinds(); + const LowLevelTypeKindSet AnyTypes = anyValueKinds(); + const LowLevelTypeKindSet IntTypes = integerKinds(); + const LowLevelTypeKindSet IntegerOrPointers = integerOrPointerKinds(); + const LowLevelTypeKindSet ScalarValues = scalarValueKinds(); + const LowLevelTypeKindSet ScalarInts = scalarIntegerKinds(); + const LowLevelTypeKindSet ScalarIntegerOrPointers = scalarIntegerOrPointerKinds(); + const LowLevelTypeKindSet FloatTypes = floatingKinds(); + const LowLevelTypeKindSet ScalarFloats = scalarFloatingKinds(); + const LowLevelTypeKindSet PointerTypes = pointerKinds(); + const LowLevelTypeKindSet ScalarPointers = scalarPointerKinds(); + const LowLevelTypeKindSet VectorTypes = vectorKinds(); const auto AnyDef0 = typedRegister(RegisterOperandRole::Def, AnyTypes, 0); const auto AnyUse0 = typedRegister(RegisterOperandRole::Use, AnyTypes, 0); @@ -1414,16 +1412,17 @@ void configureGenericOpcodes(DescriptorRegistry &Registry) { Registry.configure({GO::G_STRICT_FADD, GO::G_STRICT_FSUB, GO::G_STRICT_FMUL, GO::G_STRICT_FDIV, GO::G_STRICT_FREM}, - {FloatDef0, FloatUse0, FloatUse0}, 1, {InstructionFlag::HasSideEffects}); + {FloatDef0, FloatUse0, FloatUse0}, 1, + {InstructionFlag::HasSideEffects, InstructionFlag::MayRaiseFPException}); Registry.configure({GO::G_STRICT_FMA}, {FloatDef0, FloatUse0, FloatUse0, FloatUse0}, 1, - {InstructionFlag::HasSideEffects}); + {InstructionFlag::HasSideEffects, InstructionFlag::MayRaiseFPException}); Registry.configure({GO::G_STRICT_FSQRT}, {FloatDef0, FloatUse0}, 1, - {InstructionFlag::HasSideEffects}); + {InstructionFlag::HasSideEffects, InstructionFlag::MayRaiseFPException}); Registry.configure({GO::G_STRICT_FLDEXP}, {FloatDef0, FloatUse0, IntUse1}, 1, - {InstructionFlag::HasSideEffects}); + {InstructionFlag::HasSideEffects, InstructionFlag::MayRaiseFPException}); Registry.configure({GO::G_STRICT_FCMP, GO::G_STRICT_FCMPS}, {IntDef0, kind(MachineOperand::Kind::Predicate), FloatUse1, FloatUse1}, 1, - {InstructionFlag::HasSideEffects}); + {InstructionFlag::HasSideEffects, InstructionFlag::MayRaiseFPException}); Registry.configure({GO::G_READ_REGISTER}, {AnyDef0, kind(MachineOperand::Kind::Metadata)}, 1, {InstructionFlag::HasSideEffects, InstructionFlag::Convergent}); Registry.configure({GO::G_WRITE_REGISTER}, {kind(MachineOperand::Kind::Metadata), AnyUse0}, 0, diff --git a/backend/lib/CodeGen/InstructionDescriptor.cpp b/backend/lib/CodeGen/InstructionDescriptor.cpp index 2c99939..d164cde 100644 --- a/backend/lib/CodeGen/InstructionDescriptor.cpp +++ b/backend/lib/CodeGen/InstructionDescriptor.cpp @@ -80,7 +80,7 @@ namespace { } if (Operand.TypeConstraint) { if (!isRegisterOnly(Operand.Kinds) || Operand.TypeConstraint->Kinds.empty() || - Operand.TypeConstraint->Kinds.contains(LLT::Kind::Invalid)) { + Operand.TypeConstraint->Kinds.contains(LowLevelType::Kind::Invalid)) { return makeUnexpected(ErrorCode::InvalidArgument, "typed operand descriptor requires a nonempty register type set"); } @@ -307,8 +307,8 @@ OperandKindSet::OperandKindSet(std::initializer_list<MachineOperand::Kind> Kinds add(Kind); } -LLTKindSet::LLTKindSet(std::initializer_list<LLT::Kind> Kinds) noexcept { - for (const LLT::Kind Kind : Kinds) +LowLevelTypeKindSet::LowLevelTypeKindSet(std::initializer_list<LowLevelType::Kind> Kinds) noexcept { + for (const LowLevelType::Kind Kind : Kinds) add(Kind); } @@ -386,7 +386,7 @@ Expected<void> InstructionSet::validateExplicitOperands(const InstructionDescrip return std::unexpected(Shape.error()); bool SawUse = false; - std::unordered_map<std::uint16_t, LLT> EqualityGroups; + std::unordered_map<std::uint16_t, LowLevelType> EqualityGroups; for (std::size_t Index = 0; Index < Operands.size(); ++Index) { const MachineOperand &Operand = Operands[Index]; if (Operand.isImplicit()) { @@ -423,22 +423,24 @@ Expected<void> InstructionSet::validateExplicitOperands(const InstructionDescrip auto Info = RegInfo.virtualRegisterInfo(*Reg); if (!Info) return std::unexpected(Info.error()); - const std::optional<LLT> &RegisterType = Info->get().Type; + const std::optional<LowLevelType> &RegisterType = Info->get().Type; if (!RegisterType) { return makeUnexpected(ErrorCode::VerificationError, - "typed instruction operand virtual register has no LLT"); + "typed instruction operand virtual register has no LowLevelType"); } - const LLT Type = RegisterType.value(); + const LowLevelType Type = RegisterType.value(); if (!OperandDesc.TypeConstraint->Kinds.contains(Type.kind())) { - return makeUnexpected(ErrorCode::VerificationError, - "instruction operand LLT kind is not permitted by its descriptor"); + return makeUnexpected( + ErrorCode::VerificationError, + "instruction operand LowLevelType kind is not permitted by its descriptor"); } if (OperandDesc.TypeConstraint->EqualityGroup) { const auto [Position, Inserted] = EqualityGroups.emplace(*OperandDesc.TypeConstraint->EqualityGroup, Type); if (!Inserted && Position->second != Type) { - return makeUnexpected(ErrorCode::VerificationError, - "instruction operands in one LLT group have different types"); + return makeUnexpected( + ErrorCode::VerificationError, + "instruction operands in one LowLevelType group have different types"); } } } diff --git a/backend/lib/CodeGen/LowLevelType.cpp b/backend/lib/CodeGen/LowLevelType.cpp index b50ea6b..50ee0e6 100644 --- a/backend/lib/CodeGen/LowLevelType.cpp +++ b/backend/lib/CodeGen/LowLevelType.cpp @@ -8,130 +8,99 @@ namespace rcc { namespace { -[[nodiscard]] LLT::Kind getVectorKind(LLT ElementType) noexcept { +[[nodiscard]] LowLevelType::Kind getVectorKind(LowLevelType ElementType) noexcept { switch (ElementType.kind()) { - case LLT::Kind::AnyScalar: - return LLT::Kind::VectorAny; - case LLT::Kind::Integer: - return LLT::Kind::VectorInteger; - case LLT::Kind::Float: - return LLT::Kind::VectorFloat; - case LLT::Kind::Pointer: - return LLT::Kind::VectorPointer; - case LLT::Kind::Invalid: - case LLT::Kind::Token: - case LLT::Kind::VectorAny: - case LLT::Kind::VectorInteger: - case LLT::Kind::VectorFloat: - case LLT::Kind::VectorPointer: - return LLT::Kind::Invalid; + case LowLevelType::Kind::CategoryNeutralScalar: + return LowLevelType::Kind::Vector; + case LowLevelType::Kind::Pointer: + return LowLevelType::Kind::VectorPointer; + case LowLevelType::Kind::Invalid: + case LowLevelType::Kind::Token: + case LowLevelType::Kind::Vector: + case LowLevelType::Kind::VectorPointer: + return LowLevelType::Kind::Invalid; } - return LLT::Kind::Invalid; + return LowLevelType::Kind::Invalid; } } // namespace -Expected<LLT> LLT::makeScalar(Kind TypeKind, std::uint64_t BitWidth) { +Expected<LowLevelType> LowLevelType::makeCategoryNeutralScalar(std::uint64_t BitWidth) { if (BitWidth == 0 || BitWidth > MaxBitWidth) { return makeUnexpected(ErrorCode::InvalidArgument, - "LLT bit width must be in the range [1, 65535]"); + "LowLevelType bit width must be in the range [1, 65535]"); } - return LLT(encode(TypeKind, static_cast<std::uint32_t>(BitWidth), 0, 0, false)); + return LowLevelType( + encode(Kind::CategoryNeutralScalar, static_cast<std::uint32_t>(BitWidth), 0, 0, false)); } -Expected<LLT> LLT::makeAnyScalar(std::uint64_t BitWidth) { - return makeScalar(Kind::AnyScalar, BitWidth); -} - -Expected<LLT> LLT::makeInteger(std::uint64_t BitWidth) { - return makeScalar(Kind::Integer, BitWidth); -} - -Expected<LLT> LLT::makeFloat(FloatSemantics Semantics) { - const auto BitWidth = getFloatSemanticsBitWidth(Semantics); - if (!BitWidth) { - return makeUnexpected(ErrorCode::InvalidArgument, "unknown floating-point semantics"); - } - - return LLT(encode(Kind::Float, *BitWidth, 0, static_cast<std::uint32_t>(Semantics), false)); -} - -Expected<LLT> LLT::makePointer(std::uint64_t AddressSpace, std::uint64_t BitWidth) { +Expected<LowLevelType> LowLevelType::makePointer(std::uint64_t AddressSpace, + std::uint64_t BitWidth) { if (BitWidth == 0 || BitWidth > MaxBitWidth) { return makeUnexpected(ErrorCode::InvalidArgument, - "LLT pointer bit width must be in the range [1, 65535]"); + "LowLevelType pointer bit width must be in the range [1, 65535]"); } if (AddressSpace > MaxAddressSpace) { - return makeUnexpected(ErrorCode::InvalidArgument, "LLT address space must fit in 24 bits"); + return makeUnexpected(ErrorCode::InvalidArgument, + "LowLevelType address space must fit in 24 bits"); } - return LLT(encode(Kind::Pointer, static_cast<std::uint32_t>(BitWidth), 0, - static_cast<std::uint32_t>(AddressSpace), false)); + return LowLevelType(encode(Kind::Pointer, static_cast<std::uint32_t>(BitWidth), 0, + static_cast<std::uint32_t>(AddressSpace), false)); } -Expected<LLT> LLT::makeFixedVector(std::uint64_t ElementCount, LLT ElementType) { +Expected<LowLevelType> LowLevelType::makeFixedVector(std::uint64_t ElementCount, + LowLevelType ElementType) { return makeVector(ElementCount, false, ElementType); } -Expected<LLT> LLT::makeScalableVector(std::uint64_t MinimumElementCount, LLT ElementType) { +Expected<LowLevelType> LowLevelType::makeScalableVector(std::uint64_t MinimumElementCount, + LowLevelType ElementType) { return makeVector(MinimumElementCount, true, ElementType); } -Expected<LLT> LLT::makeVector(std::uint64_t ElementCount, bool IsScalable, LLT ElementType) { +Expected<LowLevelType> LowLevelType::makeVector(std::uint64_t ElementCount, bool IsScalable, + LowLevelType ElementType) { if (ElementCount == 0 || ElementCount > MaxElementCount) { return makeUnexpected(ErrorCode::InvalidArgument, - "LLT vector element count must be in the range [1, 65535]"); + "LowLevelType vector element count must be in the range [1, 65535]"); } if (!IsScalable && ElementCount == 1) { return makeUnexpected(ErrorCode::InvalidArgument, - "a fixed LLT vector must contain at least two elements"); + "a fixed LowLevelType vector must contain at least two elements"); } const Kind VectorKind = getVectorKind(ElementType); if (VectorKind == Kind::Invalid) { return makeUnexpected(ErrorCode::InvalidArgument, - "LLT vector elements must be non-vector value types"); + "LowLevelType vector elements must be non-vector value types"); } std::uint32_t Auxiliary = 0; if (ElementType.isPointer()) Auxiliary = *ElementType.addressSpace(); - else if (ElementType.isFloat()) - Auxiliary = static_cast<std::uint32_t>(*ElementType.floatSemantics()); - return LLT(encode(VectorKind, ElementType.scalarBitWidth(), - static_cast<std::uint32_t>(ElementCount), Auxiliary, IsScalable)); + return LowLevelType(encode(VectorKind, ElementType.scalarBitWidth(), + static_cast<std::uint32_t>(ElementCount), Auxiliary, IsScalable)); } -std::optional<std::uint32_t> LLT::addressSpace() const noexcept { +std::optional<std::uint32_t> LowLevelType::addressSpace() const noexcept { if (!isPointerOrPointerVector()) return std::nullopt; return auxiliaryValue(); } -std::optional<FloatSemantics> LLT::floatSemantics() const noexcept { - if (!isFloatOrFloatVector()) - return std::nullopt; - return static_cast<FloatSemantics>(auxiliaryValue()); -} - -std::optional<LLT> LLT::scalarElementType() const noexcept { +std::optional<LowLevelType> LowLevelType::scalarElementType() const noexcept { switch (kind()) { - case Kind::VectorAny: - return LLT(encode(Kind::AnyScalar, scalarBitWidth(), 0, 0, false)); - case Kind::VectorInteger: - return LLT(encode(Kind::Integer, scalarBitWidth(), 0, 0, false)); - case Kind::VectorFloat: - return LLT(encode(Kind::Float, scalarBitWidth(), 0, auxiliaryValue(), false)); + case Kind::Vector: + return LowLevelType(encode(Kind::CategoryNeutralScalar, scalarBitWidth(), 0, 0, false)); case Kind::VectorPointer: - return LLT(encode(Kind::Pointer, scalarBitWidth(), 0, auxiliaryValue(), false)); + return LowLevelType(encode(Kind::Pointer, scalarBitWidth(), 0, auxiliaryValue(), false)); case Kind::Invalid: case Kind::Token: - case Kind::AnyScalar: - case Kind::Integer: - case Kind::Float: + case Kind::CategoryNeutralScalar: case Kind::Pointer: return std::nullopt; } @@ -139,7 +108,7 @@ std::optional<LLT> LLT::scalarElementType() const noexcept { return std::nullopt; } -std::string LLT::toString() const { +std::string LowLevelType::toString() const { if (!isValid()) return "LLT_invalid"; if (isToken()) @@ -147,19 +116,10 @@ std::string LLT::toString() const { std::string ScalarSpelling; switch (kind()) { - case Kind::AnyScalar: - case Kind::VectorAny: + case Kind::CategoryNeutralScalar: + case Kind::Vector: ScalarSpelling = "s" + std::to_string(scalarBitWidth()); break; - case Kind::Integer: - case Kind::VectorInteger: - ScalarSpelling = "i" + std::to_string(scalarBitWidth()); - break; - case Kind::Float: - case Kind::VectorFloat: - ScalarSpelling = - std::string(getFloatSemanticsSpelling(static_cast<FloatSemantics>(auxiliaryValue()))); - break; case Kind::Pointer: case Kind::VectorPointer: ScalarSpelling = diff --git a/backend/lib/CodeGen/MIRParser/MIParser.cpp b/backend/lib/CodeGen/MIRParser/MIParser.cpp index 5932111..b21e713 100644 --- a/backend/lib/CodeGen/MIRParser/MIParser.cpp +++ b/backend/lib/CodeGen/MIRParser/MIParser.cpp @@ -159,7 +159,7 @@ namespace { return APInt::create(BitWidth, Words); } -[[nodiscard]] std::optional<std::uint64_t> minimumTypeSizeInBits(LLT Type) noexcept { +[[nodiscard]] std::optional<std::uint64_t> minimumTypeSizeInBits(LowLevelType Type) noexcept { if (!Type.isValid() || Type.isToken()) return std::nullopt; const std::uint64_t ScalarSize = Type.scalarBitWidth(); @@ -377,8 +377,8 @@ private: [[nodiscard]] bool parseSigned64(const MIToken &Token, std::int64_t &Value); [[nodiscard]] bool parseOptionalOffset(std::int64_t &Offset); [[nodiscard]] bool parseAlignment(Alignment &Result); - [[nodiscard]] bool parseLowLevelType(LLT &Result); - [[nodiscard]] bool parseScalarLowLevelType(const MIToken &Token, LLT &Result); + [[nodiscard]] bool parseLowLevelType(LowLevelType &Result); + [[nodiscard]] bool parseScalarLowLevelType(const MIToken &Token, LowLevelType &Result); [[nodiscard]] bool parseFirstPass(); [[nodiscard]] bool parseSecondPass(); @@ -553,30 +553,20 @@ bool MIParser::Impl::parseAlignment(Alignment &Result) { return false; } -bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Result) { +bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LowLevelType &Result) { if (TypeToken.kind() != MITokenKind::Identifier) return fail(TypeToken, "expected a scalar low-level type"); std::string_view Spelling = TypeToken.stringValue(); - enum class ScalarKind : std::uint8_t { - Any, - Integer, - Float, - BFloat, - Pointer, - }; - ScalarKind Kind = ScalarKind::Any; + enum class ScalarKind : std::uint8_t { CategoryNeutral, Pointer }; + ScalarKind Kind = ScalarKind::CategoryNeutral; std::string_view Digits; if (Spelling.starts_with("bf")) { - Kind = ScalarKind::BFloat; Digits = Spelling.substr(2); } else if (Spelling.starts_with('s')) { - Kind = ScalarKind::Any; Digits = Spelling.substr(1); } else if (Spelling.starts_with('i')) { - Kind = ScalarKind::Integer; Digits = Spelling.substr(1); } else if (Spelling.starts_with('f')) { - Kind = ScalarKind::Float; Digits = Spelling.substr(1); } else if (Spelling.starts_with('p')) { Kind = ScalarKind::Pointer; @@ -589,43 +579,20 @@ bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Resu if (!parseUnsignedDigits(Digits, Value)) return fail(TypeToken, "expected integers after 's'/'i'/'f'/'bf'/'p' type identifier"); - Expected<LLT> Created = makeUnexpected(ErrorCode::ParseError, "invalid low-level type"); + Expected<LowLevelType> Created = makeUnexpected(ErrorCode::ParseError, "invalid low-level type"); switch (Kind) { - case ScalarKind::Any: + case ScalarKind::CategoryNeutral: if (Value == 0) { - Result = LLT::token(); + Result = LowLevelType::token(); return false; } - Created = LLT::makeAnyScalar(Value); - break; - case ScalarKind::Integer: - Created = LLT::makeInteger(Value); - break; - case ScalarKind::Float: { - std::optional<FloatSemantics> Semantics; - if (Value == 16) - Semantics = FloatSemantics::IEEEHalf; - else if (Value == 32) - Semantics = FloatSemantics::IEEESingle; - else if (Value == 64) - Semantics = FloatSemantics::IEEEDouble; - else if (Value == 128) - Semantics = FloatSemantics::IEEEQuad; - if (!Semantics) - return fail(TypeToken, "unsupported IEEE floating low-level type width"); - Created = LLT::makeFloat(*Semantics); - break; - } - case ScalarKind::BFloat: - if (Value != 16) - return fail(TypeToken, "bfloat low-level type must have width 16"); - Created = LLT::makeFloat(FloatSemantics::BFloat); + Created = LowLevelType::makeCategoryNeutralScalar(Value); break; case ScalarKind::Pointer: if (!Context.PointerSizeInBits) return fail(TypeToken, "pointer low-level type requires an explicit pointer size"); if (auto PointerSize = Context.PointerSizeInBits(static_cast<std::uint32_t>(Value))) - Created = LLT::makePointer(Value, *PointerSize); + Created = LowLevelType::makePointer(Value, *PointerSize); else return importError(TypeToken, PointerSize.error()); break; @@ -636,7 +603,7 @@ bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Resu return false; } -bool MIParser::Impl::parseLowLevelType(LLT &Result) { +bool MIParser::Impl::parseLowLevelType(LowLevelType &Result) { const MIToken Begin = token(); const auto HasScalarPrefix = [](std::string_view Spelling) { return Spelling.starts_with('s') || Spelling.starts_with('i') || Spelling.starts_with('f') || @@ -685,7 +652,7 @@ bool MIParser::Impl::parseLowLevelType(LLT &Result) { if (!at(MITokenKind::Identifier) || !HasScalarPrefix(token().stringValue())) return VectorError(); - LLT ElementType; + LowLevelType ElementType; if (parseScalarLowLevelType(token(), ElementType)) return true; if (ElementType.isToken()) @@ -694,8 +661,9 @@ bool MIParser::Impl::parseLowLevelType(LLT &Result) { if (!consume(MITokenKind::Greater)) return VectorError(); - Expected<LLT> Created = Scalable ? LLT::makeScalableVector(ElementCount, ElementType) - : LLT::makeFixedVector(ElementCount, ElementType); + Expected<LowLevelType> Created = Scalable + ? LowLevelType::makeScalableVector(ElementCount, ElementType) + : LowLevelType::makeFixedVector(ElementCount, ElementType); if (!Created) return importError(Begin, Created.error()); Result = *Created; @@ -1078,7 +1046,7 @@ bool MIParser::Impl::parseRegisterOperand(bool IsDef, ParsedOperand &Result) { } else { if (!Reg.isVirtual()) return fail("low-level type is only valid on a virtual register"); - LLT Type; + LowLevelType Type; if (parseLowLevelType(Type)) return true; if (expect(MITokenKind::RightParen, "')' after the low-level type")) @@ -1883,7 +1851,7 @@ bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result, } else if (atKeyword("unknown-size")) { advance(); } else if (consume(MITokenKind::LeftParen)) { - LLT Type; + LowLevelType Type; if (parseLowLevelType(Type)) return true; if (expect(MITokenKind::RightParen, "')' after the memory low-level type")) @@ -1945,7 +1913,7 @@ bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result, } else if (atKeyword("addrspace")) { advance(); if (!at(MITokenKind::IntegerLiteral) || parseUnsigned32(token(), Description.AddressSpace) || - Description.AddressSpace > LLT::MaxAddressSpace) { + Description.AddressSpace > LowLevelType::MaxAddressSpace) { return fail("invalid machine memory operand address space"); } advance(); diff --git a/backend/lib/CodeGen/MIRPrinter.cpp b/backend/lib/CodeGen/MIRPrinter.cpp index d2cc8eb..1ba8ac1 100644 --- a/backend/lib/CodeGen/MIRPrinter.cpp +++ b/backend/lib/CodeGen/MIRPrinter.cpp @@ -1647,13 +1647,11 @@ namespace { return {}; } -[[nodiscard]] Expected<std::string> llvmMIRScalarLowLevelType(LLT Type) { +[[nodiscard]] Expected<std::string> llvmMIRScalarLowLevelType(LowLevelType Type) { if (Type.isToken()) return "s0"; - if (Type.isAnyScalar()) + if (Type.isCategoryNeutralScalar()) return "s" + std::to_string(Type.scalarBitWidth()); - if (Type.isInteger()) - return "i" + std::to_string(Type.scalarBitWidth()); if (Type.isPointer()) { const auto AddressSpace = Type.addressSpace(); if (!AddressSpace) { @@ -1662,49 +1660,11 @@ namespace { } return "p" + std::to_string(*AddressSpace); } - if (!Type.isFloat()) { - return makeUnexpected(ErrorCode::VerificationError, - "invalid scalar low-level type cannot be printed as LLVM MIR"); - } - - const auto Semantics = Type.floatSemantics(); - if (!Semantics) { - return makeUnexpected(ErrorCode::VerificationError, - "floating low-level type has no floating-point semantics"); - } - switch (*Semantics) { - case FloatSemantics::IEEEHalf: - return "f16"; - case FloatSemantics::BFloat: - return "bf16"; - case FloatSemantics::IEEESingle: - return "f32"; - case FloatSemantics::IEEEDouble: - return "f64"; - case FloatSemantics::IEEEQuad: - return "f128"; - case FloatSemantics::PPCDoubleDouble: - case FloatSemantics::Float8E5M2: - case FloatSemantics::Float8E5M2FNUZ: - case FloatSemantics::Float8E4M3: - case FloatSemantics::Float8E4M3FN: - case FloatSemantics::Float8E4M3FNUZ: - case FloatSemantics::Float8E4M3B11FNUZ: - case FloatSemantics::Float8E3M4: - case FloatSemantics::FloatTF32: - case FloatSemantics::Float8E8M0FNU: - case FloatSemantics::Float6E3M2FN: - case FloatSemantics::Float6E2M3FN: - case FloatSemantics::Float4E2M1FN: - case FloatSemantics::X87DoubleExtended: - case FloatSemantics::Count: - return makeUnexpected(ErrorCode::Unsupported, - "fixed LLVM MIR cannot spell this floating low-level type"); - } - return makeUnexpected(ErrorCode::InternalError, "floating low-level type is unhandled"); + return makeUnexpected(ErrorCode::VerificationError, + "invalid scalar low-level type cannot be printed as LLVM MIR"); } -[[nodiscard]] Expected<std::string> llvmMIRLowLevelType(LLT Type) { +[[nodiscard]] Expected<std::string> llvmMIRLowLevelType(LowLevelType Type) { if (!Type.isValid()) { return makeUnexpected(ErrorCode::VerificationError, "invalid low-level type cannot be printed as LLVM MIR"); diff --git a/backend/lib/CodeGen/MachineCSE.cpp b/backend/lib/CodeGen/MachineCSE.cpp index 52a1484..30129bc 100644 --- a/backend/lib/CodeGen/MachineCSE.cpp +++ b/backend/lib/CodeGen/MachineCSE.cpp @@ -149,24 +149,7 @@ template <typename ValueT> return true; } -[[nodiscard]] bool hasFloatingRegister(const MachineInstr &Instruction, - const MachineRegisterInfo &Registers) { - for (const MachineOperand &Operand : Instruction.operands()) { - const Register *Reg = Operand.getIf<Register>(); - if (Reg == nullptr || !Reg->isVirtual()) - continue; - auto Info = Registers.virtualRegisterInfo(*Reg); - if (Info) { - const auto &Type = Info->get().Type; - if (Type && Type->isFloat()) - return true; - } - } - return false; -} - [[nodiscard]] Expected<bool> isCandidate(const MachineInstr &Instruction, - const MachineFunction &Function, const TargetDescription &Target) { const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction.opcode()); if (Descriptor == nullptr) { @@ -187,8 +170,8 @@ template <typename ValueT> return false; if (!Flags.has(InstructionFlag::MayLoad) && !Instruction.memOperands().empty()) return false; - if (!Instruction.flags().has(MachineInstrFlag::NoFPExcept) && - hasFloatingRegister(Instruction, Function.registerInfo())) { + if (Flags.has(InstructionFlag::MayRaiseFPException) && + !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) { return false; } @@ -351,7 +334,7 @@ MachineCSEPass::runImplementation(MachineFunction &Function, const TargetDescrip Block = Block->next()) { for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr;) { MachineInstr *Next = Instruction->next(); - auto Candidate = isCandidate(*Instruction, Function, Target); + auto Candidate = isCandidate(*Instruction, Target); if (!Candidate) return std::unexpected(Candidate.error()); if (!*Candidate) { diff --git a/backend/lib/CodeGen/MachineLICM.cpp b/backend/lib/CodeGen/MachineLICM.cpp index 8a34d3b..627e59f 100644 --- a/backend/lib/CodeGen/MachineLICM.cpp +++ b/backend/lib/CodeGen/MachineLICM.cpp @@ -113,6 +113,9 @@ namespace { hasProtectedAttachment(Instruction) || !Instruction.memOperands().empty()) { return false; } + if (Flags.has(InstructionFlag::MayRaiseFPException) && + !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) + return false; bool HasDefinition = false; for (const MachineOperand &Operand : Instruction.operands()) { @@ -141,14 +144,6 @@ namespace { auto Info = Function.registerInfo().virtualRegisterInfo(*Reg); if (!Info) return std::unexpected(Info.error()); - const auto &Type = Info->get().Type; - if (Type && Type->isFloat() && !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) { - return false; - } - } - if (Stage == MachineCodeMotionStage::PostRegisterAllocation && - !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) { - return false; } return HasDefinition; } diff --git a/backend/lib/CodeGen/MachineMemOperand.cpp b/backend/lib/CodeGen/MachineMemOperand.cpp index cb90e61..0ae6941 100644 --- a/backend/lib/CodeGen/MachineMemOperand.cpp +++ b/backend/lib/CodeGen/MachineMemOperand.cpp @@ -257,7 +257,7 @@ Expected<MachineMemOperand> MachineMemOperand::create(MachineMemOperandDesc Desc return makeUnexpected(ErrorCode::InvalidArgument, "machine memory operand must describe a load or store"); } - if (Description.AddressSpace > LLT::MaxAddressSpace) { + if (Description.AddressSpace > LowLevelType::MaxAddressSpace) { return makeUnexpected(ErrorCode::InvalidArgument, "machine memory operand address space must fit in 24 bits"); } diff --git a/backend/lib/CodeGen/MachineRegisterInfo.cpp b/backend/lib/CodeGen/MachineRegisterInfo.cpp index ccd7d89..a88bfb0 100644 --- a/backend/lib/CodeGen/MachineRegisterInfo.cpp +++ b/backend/lib/CodeGen/MachineRegisterInfo.cpp @@ -68,9 +68,10 @@ Expected<Register> MachineRegisterInfo::createVirtualRegister() { return *Reg; } -Expected<Register> MachineRegisterInfo::createVirtualRegister(LLT Type) { +Expected<Register> MachineRegisterInfo::createVirtualRegister(LowLevelType Type) { if (!Type.isValid()) { - return makeUnexpected(ErrorCode::InvalidArgument, "virtual register type must be a valid LLT"); + return makeUnexpected(ErrorCode::InvalidArgument, + "virtual register type must be a valid LowLevelType"); } auto Reg = createVirtualRegister(); @@ -124,9 +125,10 @@ MachineRegisterInfo::virtualRegisterInfo(Register Reg) const { return std::cref(VirtualRegisters[*Index]); } -Expected<void> MachineRegisterInfo::setType(Register Reg, LLT Type) { +Expected<void> MachineRegisterInfo::setType(Register Reg, LowLevelType Type) { if (!Type.isValid()) { - return makeUnexpected(ErrorCode::InvalidArgument, "virtual register type must be a valid LLT"); + return makeUnexpected(ErrorCode::InvalidArgument, + "virtual register type must be a valid LowLevelType"); } auto Info = virtualRegisterInfo(Reg); if (!Info) diff --git a/backend/lib/CodeGen/MachineSink.cpp b/backend/lib/CodeGen/MachineSink.cpp index 7c540e0..95f902d 100644 --- a/backend/lib/CodeGen/MachineSink.cpp +++ b/backend/lib/CodeGen/MachineSink.cpp @@ -90,6 +90,9 @@ namespace { hasProtectedAttachment(Instruction) || !Instruction.memOperands().empty()) { return false; } + if (Flags.has(InstructionFlag::MayRaiseFPException) && + !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) + return false; bool HasDefinition = false; for (const MachineOperand &Operand : Instruction.operands()) { @@ -118,14 +121,6 @@ namespace { auto Info = Function.registerInfo().virtualRegisterInfo(*Reg); if (!Info) return std::unexpected(Info.error()); - const auto &Type = Info->get().Type; - if (Type && Type->isFloat() && !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) { - return false; - } - } - if (Stage == MachineCodeMotionStage::PostRegisterAllocation && - !Instruction.flags().has(MachineInstrFlag::NoFPExcept)) { - return false; } return HasDefinition; } diff --git a/backend/lib/CodeGen/MachineVerifier.cpp b/backend/lib/CodeGen/MachineVerifier.cpp index 725a288..14ce8ef 100644 --- a/backend/lib/CodeGen/MachineVerifier.cpp +++ b/backend/lib/CodeGen/MachineVerifier.cpp @@ -849,7 +849,7 @@ private: MissingVirtualBank |= !Info.Bank; MissingVirtualClass |= !Info.RegClass; if (Info.Type && !Info.Type->isValid()) - return fail("virtual register has an invalid LLT"); + return fail("virtual register has an invalid LowLevelType"); std::unordered_set<PhysicalRegister> Hints; for (const PhysicalRegister Hint : Info.AllocationHints) { @@ -924,7 +924,7 @@ private: Has(MachineFunctionProperty::Legalized) || Has(MachineFunctionProperty::RegBankSelected); if (NeedsTypes && MissingVirtualType) - return fail("typed pipeline stage has a virtual register without LLT"); + return fail("typed pipeline stage has a virtual register without LowLevelType"); if (Options.Mode == MachineVerifierMode::PreLegalizer) { if (!Has(MachineFunctionProperty::IsSSA) || !Has(MachineFunctionProperty::TracksLiveness)) { diff --git a/backend/lib/CodeGen/TargetDescription.cpp b/backend/lib/CodeGen/TargetDescription.cpp index e8c7d79..b9569be 100644 --- a/backend/lib/CodeGen/TargetDescription.cpp +++ b/backend/lib/CodeGen/TargetDescription.cpp @@ -30,7 +30,7 @@ namespace { return Descriptor.Operands.back(); } -[[nodiscard]] std::uint64_t minimumTypeSizeInBits(LLT Type) noexcept { +[[nodiscard]] std::uint64_t minimumTypeSizeInBits(LowLevelType Type) noexcept { if (Type.isToken()) return 0; const std::uint64_t ScalarSize = Type.scalarBitWidth(); |
