aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'backend/lib/CodeGen')
-rw-r--r--backend/lib/CodeGen/GenericOpcodes.cpp191
-rw-r--r--backend/lib/CodeGen/InstructionDescriptor.cpp24
-rw-r--r--backend/lib/CodeGen/LowLevelType.cpp124
-rw-r--r--backend/lib/CodeGen/MIRParser/MIParser.cpp70
-rw-r--r--backend/lib/CodeGen/MIRPrinter.cpp50
-rw-r--r--backend/lib/CodeGen/MachineCSE.cpp23
-rw-r--r--backend/lib/CodeGen/MachineLICM.cpp11
-rw-r--r--backend/lib/CodeGen/MachineMemOperand.cpp2
-rw-r--r--backend/lib/CodeGen/MachineRegisterInfo.cpp10
-rw-r--r--backend/lib/CodeGen/MachineSink.cpp11
-rw-r--r--backend/lib/CodeGen/MachineVerifier.cpp4
-rw-r--r--backend/lib/CodeGen/TargetDescription.cpp2
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();