aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-13 23:55:38 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-13 23:55:38 +0800
commitaa69e15c6909c3b162b15f5326f0a72ba9bb7163 (patch)
tree6428eb20e41bad1fc8ad2f5c259bc5537f54554d /backend
parentcd30fb546e389d1fb78ce8e579b3dba3a8fdb52a (diff)
downloadrcc-project-aa69e15c6909c3b162b15f5326f0a72ba9bb7163.tar.gz
rcc-project-aa69e15c6909c3b162b15f5326f0a72ba9bb7163.tar.xz
[CodeGen] Unify scalar low-level types
Diffstat (limited to 'backend')
-rw-r--r--backend/include/rcc/CodeGen/InstructionDescriptor.h18
-rw-r--r--backend/include/rcc/CodeGen/LowLevelType.h89
-rw-r--r--backend/include/rcc/CodeGen/MachineMemOperand.h2
-rw-r--r--backend/include/rcc/CodeGen/MachineRegisterInfo.h6
-rw-r--r--backend/include/rcc/CodeGen/TargetCallLowering.h17
-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
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp72
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp261
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp452
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp15
-rw-r--r--backend/lib/Target/RISCV/RISCV.rccdesc88
-rw-r--r--backend/lib/Target/RISCV/RISCVPseudoExpansion.cpp5
-rw-r--r--backend/lib/Tooling/MIRFuzzer.cpp2
-rw-r--r--backend/unittests/CodeGen/CoreTypesTest.cpp150
-rw-r--r--backend/unittests/CodeGen/GenericOpcodesTest.cpp60
-rw-r--r--backend/unittests/CodeGen/GlobalISel/GISelMITest.h8
-rw-r--r--backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp6
-rw-r--r--backend/unittests/CodeGen/InstructionDescriptorTest.cpp4
-rw-r--r--backend/unittests/CodeGen/LiveTestSupport.h2
-rw-r--r--backend/unittests/CodeGen/MachineAnalysesTest.cpp8
-rw-r--r--backend/unittests/CodeGen/MachineFunctionClonerTest.cpp2
-rw-r--r--backend/unittests/CodeGen/MachineIRBuilderTest.cpp6
-rw-r--r--backend/unittests/CodeGen/MachineIRCoreTest.cpp7
-rw-r--r--backend/unittests/CodeGen/MachineOptimizationTest.cpp6
-rw-r--r--backend/unittests/CodeGen/MachineSchedulingTest.cpp6
-rw-r--r--backend/unittests/CodeGen/MachineValueTypesTest.cpp4
-rw-r--r--backend/unittests/CodeGen/MachineVerifierTargetTest.cpp16
-rw-r--r--backend/unittests/CodeGen/MachineVerifierTest.cpp8
-rw-r--r--backend/unittests/CodeGen/PHIEliminationTest.cpp16
-rw-r--r--backend/unittests/CodeGen/RegisterAllocationTest.cpp2
-rw-r--r--backend/unittests/CodeGen/RegisterAllocationTestSupport.h2
-rw-r--r--backend/unittests/CodeGen/SSAExitTestSupport.h2
-rw-r--r--backend/unittests/CodeGen/TargetCallLoweringTest.cpp8
-rw-r--r--backend/unittests/CodeGen/TargetRegisterInfoTest.cpp4
-rw-r--r--backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp4
-rw-r--r--backend/unittests/MIR/MIParserTest.cpp38
-rw-r--r--backend/unittests/MIR/MIRDocumentTest.cpp4
-rw-r--r--backend/unittests/Target/RISCVCallLoweringTest.cpp61
-rw-r--r--backend/unittests/Target/RISCVCodeGenTest.cpp178
-rw-r--r--backend/unittests/Target/RISCVLateCodeGenTest.cpp6
-rw-r--r--backend/unittests/Target/RISCVRegisterAllocationTest.cpp9
-rw-r--r--backend/unittests/Target/RISCVSSAExitTest.cpp11
-rw-r--r--backend/utils/TableGen/Common/CodeGenInstruction.cpp3
54 files changed, 994 insertions, 1196 deletions
diff --git a/backend/include/rcc/CodeGen/InstructionDescriptor.h b/backend/include/rcc/CodeGen/InstructionDescriptor.h
index 15d2162..ddc42e8 100644
--- a/backend/include/rcc/CodeGen/InstructionDescriptor.h
+++ b/backend/include/rcc/CodeGen/InstructionDescriptor.h
@@ -67,24 +67,24 @@ private:
std::uint32_t Mask = 0;
};
-class LLTKindSet final {
+class LowLevelTypeKindSet final {
public:
- static_assert(static_cast<std::uint32_t>(LLT::Kind::VectorPointer) < 16);
+ static_assert(static_cast<std::uint32_t>(LowLevelType::Kind::VectorPointer) < 16);
- constexpr LLTKindSet() noexcept = default;
+ constexpr LowLevelTypeKindSet() noexcept = default;
- LLTKindSet(std::initializer_list<LLT::Kind> Kinds) noexcept;
+ LowLevelTypeKindSet(std::initializer_list<LowLevelType::Kind> Kinds) noexcept;
[[nodiscard]] constexpr bool empty() const noexcept {
return Mask == 0;
}
- [[nodiscard]] constexpr bool contains(LLT::Kind Kind) const noexcept {
+ [[nodiscard]] constexpr bool contains(LowLevelType::Kind Kind) const noexcept {
const auto Index = static_cast<std::uint32_t>(Kind);
return Index < 16 && (Mask & (std::uint16_t{1} << Index)) != 0;
}
- constexpr void add(LLT::Kind Kind) noexcept {
+ constexpr void add(LowLevelType::Kind Kind) noexcept {
const auto Index = static_cast<std::uint32_t>(Kind);
if (Index < 16)
Mask |= std::uint16_t{1} << Index;
@@ -94,7 +94,8 @@ public:
return Mask;
}
- friend constexpr bool operator==(LLTKindSet Left, LLTKindSet Right) noexcept = default;
+ friend constexpr bool operator==(LowLevelTypeKindSet Left,
+ LowLevelTypeKindSet Right) noexcept = default;
private:
std::uint16_t Mask = 0;
@@ -117,7 +118,7 @@ enum class MemoryOperandRole : std::uint8_t {
};
struct OperandTypeConstraint final {
- LLTKindSet Kinds;
+ LowLevelTypeKindSet Kinds;
std::optional<std::uint16_t> EqualityGroup;
};
@@ -141,6 +142,7 @@ enum class InstructionFlag : std::uint8_t {
NotDuplicable,
Convergent,
UnmodeledSideEffects,
+ MayRaiseFPException,
Phi,
FakeUse,
Generic,
diff --git a/backend/include/rcc/CodeGen/LowLevelType.h b/backend/include/rcc/CodeGen/LowLevelType.h
index e6ff174..d35d30d 100644
--- a/backend/include/rcc/CodeGen/LowLevelType.h
+++ b/backend/include/rcc/CodeGen/LowLevelType.h
@@ -3,7 +3,6 @@
#ifndef RCC_CODEGEN_LOWLEVELTYPE_H
#define RCC_CODEGEN_LOWLEVELTYPE_H
-#include "rcc/ADT/APFloat.h"
#include "rcc/Support/Error.h"
#include <cstddef>
@@ -16,18 +15,14 @@
namespace rcc {
-class LLT final {
+class LowLevelType final {
public:
enum class Kind : std::uint8_t {
Invalid,
Token,
- AnyScalar,
- Integer,
- Float,
+ CategoryNeutralScalar,
Pointer,
- VectorAny,
- VectorInteger,
- VectorFloat,
+ Vector,
VectorPointer,
};
@@ -35,20 +30,19 @@ public:
static constexpr std::uint32_t MaxElementCount = (std::uint32_t{1} << 16) - 1;
static constexpr std::uint32_t MaxAddressSpace = (std::uint32_t{1} << 24) - 1;
- constexpr LLT() noexcept = default;
+ constexpr LowLevelType() noexcept = default;
- [[nodiscard]] static constexpr LLT token() noexcept {
- return LLT(encode(Kind::Token, 0, 0, 0, false));
+ [[nodiscard]] static constexpr LowLevelType token() noexcept {
+ return LowLevelType(encode(Kind::Token, 0, 0, 0, false));
}
- [[nodiscard]] static Expected<LLT> makeAnyScalar(std::uint64_t BitWidth);
- [[nodiscard]] static Expected<LLT> makeInteger(std::uint64_t BitWidth);
- [[nodiscard]] static Expected<LLT> makeFloat(FloatSemantics Semantics);
- [[nodiscard]] static Expected<LLT> makePointer(std::uint64_t AddressSpace,
- std::uint64_t BitWidth);
- [[nodiscard]] static Expected<LLT> makeFixedVector(std::uint64_t ElementCount, LLT ElementType);
- [[nodiscard]] static Expected<LLT> makeScalableVector(std::uint64_t MinimumElementCount,
- LLT ElementType);
+ [[nodiscard]] static Expected<LowLevelType> makeCategoryNeutralScalar(std::uint64_t BitWidth);
+ [[nodiscard]] static Expected<LowLevelType> makePointer(std::uint64_t AddressSpace,
+ std::uint64_t BitWidth);
+ [[nodiscard]] static Expected<LowLevelType> makeFixedVector(std::uint64_t ElementCount,
+ LowLevelType ElementType);
+ [[nodiscard]] static Expected<LowLevelType> makeScalableVector(std::uint64_t MinimumElementCount,
+ LowLevelType ElementType);
[[nodiscard]] constexpr Kind kind() const noexcept {
return static_cast<Kind>((RawValue >> KindShift) & KindMask);
@@ -62,53 +56,28 @@ public:
return kind() == Kind::Token;
}
- [[nodiscard]] constexpr bool isAnyScalar() const noexcept {
- return kind() == Kind::AnyScalar;
- }
-
- [[nodiscard]] constexpr bool isInteger() const noexcept {
- return kind() == Kind::Integer;
- }
-
- [[nodiscard]] constexpr bool isFloat() const noexcept {
- return kind() == Kind::Float;
+ [[nodiscard]] constexpr bool isCategoryNeutralScalar() const noexcept {
+ return kind() == Kind::CategoryNeutralScalar;
}
[[nodiscard]] constexpr bool isPointer() const noexcept {
return kind() == Kind::Pointer;
}
- [[nodiscard]] constexpr bool isAnyVector() const noexcept {
- return kind() == Kind::VectorAny;
- }
-
- [[nodiscard]] constexpr bool isIntegerVector() const noexcept {
- return kind() == Kind::VectorInteger;
- }
-
- [[nodiscard]] constexpr bool isFloatVector() const noexcept {
- return kind() == Kind::VectorFloat;
+ [[nodiscard]] constexpr bool isVectorValue() const noexcept {
+ return kind() == Kind::Vector;
}
[[nodiscard]] constexpr bool isPointerVector() const noexcept {
return kind() == Kind::VectorPointer;
}
- [[nodiscard]] constexpr bool isIntegerOrIntegerVector() const noexcept {
- return isInteger() || isIntegerVector();
- }
-
- [[nodiscard]] constexpr bool isFloatOrFloatVector() const noexcept {
- return isFloat() || isFloatVector();
- }
-
[[nodiscard]] constexpr bool isPointerOrPointerVector() const noexcept {
return isPointer() || isPointerVector();
}
[[nodiscard]] constexpr bool isVector() const noexcept {
- return kind() == Kind::VectorAny || kind() == Kind::VectorInteger ||
- kind() == Kind::VectorFloat || kind() == Kind::VectorPointer;
+ return kind() == Kind::Vector || kind() == Kind::VectorPointer;
}
[[nodiscard]] constexpr bool isScalableVector() const noexcept {
@@ -116,7 +85,7 @@ public:
}
[[nodiscard]] constexpr bool isScalarValue() const noexcept {
- return isAnyScalar() || isInteger() || isFloat() || isPointer();
+ return isCategoryNeutralScalar() || isPointer();
}
[[nodiscard]] constexpr std::uint32_t scalarBitWidth() const noexcept {
@@ -130,8 +99,7 @@ public:
}
[[nodiscard]] std::optional<std::uint32_t> addressSpace() const noexcept;
- [[nodiscard]] std::optional<FloatSemantics> floatSemantics() const noexcept;
- [[nodiscard]] std::optional<LLT> scalarElementType() const noexcept;
+ [[nodiscard]] std::optional<LowLevelType> scalarElementType() const noexcept;
[[nodiscard]] constexpr std::uint64_t rawValue() const noexcept {
return RawValue;
@@ -139,7 +107,7 @@ public:
[[nodiscard]] std::string toString() const;
- friend constexpr bool operator==(LLT Left, LLT Right) noexcept = default;
+ friend constexpr bool operator==(LowLevelType Left, LowLevelType Right) noexcept = default;
private:
static constexpr unsigned BitWidthShift = 0;
@@ -153,7 +121,7 @@ private:
static constexpr std::uint64_t AuxiliaryMask = (std::uint64_t{1} << 24) - 1;
static constexpr std::uint64_t KindMask = (std::uint64_t{1} << 4) - 1;
- explicit constexpr LLT(std::uint64_t RawValue) noexcept : RawValue(RawValue) {}
+ explicit constexpr LowLevelType(std::uint64_t RawValue) noexcept : RawValue(RawValue) {}
[[nodiscard]] static constexpr std::uint64_t encode(Kind TypeKind, std::uint32_t BitWidth,
std::uint32_t ElementCount,
@@ -166,9 +134,8 @@ private:
(static_cast<std::uint64_t>(BitWidth) << BitWidthShift);
}
- [[nodiscard]] static Expected<LLT> makeScalar(Kind TypeKind, std::uint64_t BitWidth);
- [[nodiscard]] static Expected<LLT> makeVector(std::uint64_t ElementCount, bool IsScalable,
- LLT ElementType);
+ [[nodiscard]] static Expected<LowLevelType> makeVector(std::uint64_t ElementCount,
+ bool IsScalable, LowLevelType ElementType);
[[nodiscard]] constexpr std::uint32_t auxiliaryValue() const noexcept {
return static_cast<std::uint32_t>((RawValue >> AuxiliaryShift) & AuxiliaryMask);
@@ -177,13 +144,13 @@ private:
std::uint64_t RawValue = 0;
};
-static_assert(sizeof(LLT) == sizeof(std::uint64_t));
-static_assert(std::is_trivially_copyable_v<LLT>);
+static_assert(sizeof(LowLevelType) == sizeof(std::uint64_t));
+static_assert(std::is_trivially_copyable_v<LowLevelType>);
} // namespace rcc
-template <> struct std::hash<rcc::LLT> {
- [[nodiscard]] std::size_t operator()(rcc::LLT Type) const noexcept {
+template <> struct std::hash<rcc::LowLevelType> {
+ [[nodiscard]] std::size_t operator()(rcc::LowLevelType Type) const noexcept {
return std::hash<std::uint64_t>{}(Type.rawValue());
}
};
diff --git a/backend/include/rcc/CodeGen/MachineMemOperand.h b/backend/include/rcc/CodeGen/MachineMemOperand.h
index d236fd3..0ddd1b5 100644
--- a/backend/include/rcc/CodeGen/MachineMemOperand.h
+++ b/backend/include/rcc/CodeGen/MachineMemOperand.h
@@ -197,7 +197,7 @@ struct MachineMemOperandDesc final {
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic;
SyncScopeID SyncScope;
MemorySize Size;
- std::optional<LLT> MemoryType;
+ std::optional<LowLevelType> MemoryType;
Alignment Align;
std::optional<Alignment> BaseAlign;
std::uint32_t AddressSpace = 0;
diff --git a/backend/include/rcc/CodeGen/MachineRegisterInfo.h b/backend/include/rcc/CodeGen/MachineRegisterInfo.h
index 524ee77..e0538d3 100644
--- a/backend/include/rcc/CodeGen/MachineRegisterInfo.h
+++ b/backend/include/rcc/CodeGen/MachineRegisterInfo.h
@@ -81,7 +81,7 @@ private:
struct VirtualRegisterInfo final {
std::optional<std::string> Name;
- std::optional<LLT> Type;
+ std::optional<LowLevelType> Type;
std::optional<RegisterBankID> Bank;
std::optional<RegisterClassID> RegClass;
std::vector<PhysicalRegister> AllocationHints;
@@ -107,7 +107,7 @@ public:
~MachineRegisterInfo();
[[nodiscard]] Expected<Register> createVirtualRegister();
- [[nodiscard]] Expected<Register> createVirtualRegister(LLT Type);
+ [[nodiscard]] Expected<Register> createVirtualRegister(LowLevelType Type);
[[nodiscard]] Expected<void> eraseVirtualRegister(Register Reg);
[[nodiscard]] bool isKnownVirtualRegister(Register Reg) const noexcept;
@@ -119,7 +119,7 @@ public:
[[nodiscard]] Expected<std::reference_wrapper<const VirtualRegisterInfo>>
virtualRegisterInfo(Register Reg) const;
- [[nodiscard]] Expected<void> setType(Register Reg, LLT Type);
+ [[nodiscard]] Expected<void> setType(Register Reg, LowLevelType Type);
[[nodiscard]] Expected<void> clearType(Register Reg);
[[nodiscard]] Expected<void> setRegisterBank(Register Reg, RegisterBankID Bank);
[[nodiscard]] Expected<void> clearRegisterBank(Register Reg);
diff --git a/backend/include/rcc/CodeGen/TargetCallLowering.h b/backend/include/rcc/CodeGen/TargetCallLowering.h
index 9d9b98b..21b5407 100644
--- a/backend/include/rcc/CodeGen/TargetCallLowering.h
+++ b/backend/include/rcc/CodeGen/TargetCallLowering.h
@@ -33,6 +33,14 @@ enum class ABIExtensionKind : std::uint8_t {
Count,
};
+enum class ABIValueCategory : std::uint8_t {
+ Invalid,
+ Integer,
+ FloatingPoint,
+ Pointer,
+ Count,
+};
+
enum class ABIValueFlag : std::uint8_t {
ByVal,
StructReturn,
@@ -71,7 +79,8 @@ private:
struct ABIValue final {
Register Value;
- LLT Type;
+ LowLevelType Type;
+ ABIValueCategory Category = ABIValueCategory::Invalid;
std::uint32_t OriginalValue = 0;
std::uint16_t FragmentIndex = 0;
std::uint16_t FragmentCount = 1;
@@ -222,8 +231,8 @@ struct CCAssignment final {
std::uint32_t OriginalValueIndex = 0;
std::uint16_t FragmentIndex = 0;
std::uint16_t FragmentCount = 1;
- LLT ValueType;
- LLT LocationType;
+ LowLevelType ValueType;
+ LowLevelType LocationType;
CCLocationKind LocationKind = CCLocationKind::Register;
std::optional<PhysicalRegister> LocationRegister;
std::optional<std::uint64_t> StackOffsetBytes;
@@ -279,7 +288,7 @@ struct VarArgLoweringState final {
struct ByValCopyAssignment final {
std::size_t ArgumentAssignmentIndex = 0;
Register Source;
- LLT PointerType;
+ LowLevelType PointerType;
std::uint64_t StackOffsetBytes = 0;
std::uint64_t SizeBytes = 0;
Alignment Align;
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();
diff --git a/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
index b4d513a..b0c22fc 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
@@ -54,25 +54,22 @@ constexpr std::uint32_t AllowedDirectCallFlags =
return Value + Increment;
}
-[[nodiscard]] std::uint64_t valueSizeBytes(LLT Type) noexcept {
+[[nodiscard]] std::uint64_t valueSizeBytes(LowLevelType Type) noexcept {
return (static_cast<std::uint64_t>(Type.scalarBitWidth()) + 7U) / 8U;
}
-[[nodiscard]] bool isSupportedFloat(LLT Type) noexcept {
- if (!Type.isFloat())
- return false;
- const auto Semantics = Type.floatSemantics();
- return Semantics &&
- (*Semantics == FloatSemantics::IEEESingle || *Semantics == FloatSemantics::IEEEDouble);
+[[nodiscard]] bool isSupportedFloat(const ABIValue &Value) noexcept {
+ return Value.Category == ABIValueCategory::FloatingPoint &&
+ (Value.Type.scalarBitWidth() == 32 || Value.Type.scalarBitWidth() == 64);
}
[[nodiscard]] Expected<PhysicalRegister> floatingRegisterView(PhysicalRegister DoubleView,
- LLT Type) {
- if (!isSupportedFloat(Type)) {
+ const ABIValue &Value) {
+ if (!isSupportedFloat(Value)) {
return makeUnexpected(ErrorCode::InvalidArgument,
"RISC-V floating-register view requires f32 or f64");
}
- if (Type.scalarBitWidth() == 64)
+ if (Value.Type.scalarBitWidth() == 64)
return DoubleView;
constexpr std::uint32_t FirstDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F0_D);
@@ -87,7 +84,7 @@ constexpr std::uint32_t AllowedDirectCallFlags =
}
[[nodiscard]] bool requiresIntegerTransport(const ABIValue &Value) noexcept {
- return !isSupportedFloat(Value.Type) || Value.Flags.has(ABIValueFlag::ByVal) ||
+ return !isSupportedFloat(Value) || Value.Flags.has(ABIValueFlag::ByVal) ||
Value.Flags.has(ABIValueFlag::StructReturn) || Value.Flags.has(ABIValueFlag::Indirect);
}
@@ -101,14 +98,21 @@ constexpr std::uint32_t AllowedDirectCallFlags =
ErrorCode::Unsupported,
"RISC-V ABI accepts explicitly classified integer, pointer, f32, and f64 scalar fragments");
}
- if (Value.Type.isFloat() && !isSupportedFloat(Value.Type)) {
+ if (Value.Category == ABIValueCategory::Invalid || Value.Category >= ABIValueCategory::Count) {
+ return makeUnexpected(ErrorCode::InvalidArgument, "RISC-V ABI value category is invalid");
+ }
+ if (Value.Category == ABIValueCategory::FloatingPoint && !isSupportedFloat(Value)) {
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V LP64 ABIs only support f32 and f64 floating fragments");
}
+ if ((Value.Category == ABIValueCategory::Pointer) != Value.Type.isPointer()) {
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "RISC-V ABI pointer category must match its pointer LowLevelType");
+ }
if (Value.Type.isPointer() && Value.Type.scalarBitWidth() != 64) {
return makeUnexpected(ErrorCode::Unsupported, "RISC-V LP64 ABIs require 64-bit pointers");
}
- if ((Value.Type.isInteger() || Value.Type.isAnyScalar()) && Value.Type.scalarBitWidth() < 64) {
+ if (Value.Category == ABIValueCategory::Integer && Value.Type.scalarBitWidth() < 64) {
if (Value.Extension == ABIExtensionKind::None) {
return makeUnexpected(ErrorCode::InvalidArgument,
"narrow RISC-V ABI integers require an explicit extension kind");
@@ -226,10 +230,9 @@ struct AssignmentState final {
bool VariadicStackOnly = false;
};
-[[nodiscard]] Expected<CCAssignment> registerAssignment(const ABIValue &Value,
- std::size_t ValueIndex,
- PhysicalRegister Location, LLT LocationType,
- bool IsVariadic, bool IsBitcast) {
+[[nodiscard]] Expected<CCAssignment>
+registerAssignment(const ABIValue &Value, std::size_t ValueIndex, PhysicalRegister Location,
+ LowLevelType LocationType, bool IsVariadic, bool IsBitcast) {
auto Align =
alignment(std::min<std::uint64_t>(Value.OriginalAlignment.bytes(), ABIStackAlignmentBytes));
if (!Align)
@@ -254,8 +257,8 @@ struct AssignmentState final {
}
[[nodiscard]] Expected<CCAssignment> stackAssignment(const ABIValue &Value, std::size_t ValueIndex,
- std::uint64_t StackOffset, LLT LocationType,
- bool IsVariadic,
+ std::uint64_t StackOffset,
+ LowLevelType LocationType, bool IsVariadic,
std::uint64_t StackAlignment) {
auto Align = alignment(StackAlignment);
if (!Align)
@@ -282,7 +285,7 @@ struct AssignmentState final {
[[nodiscard]] Expected<ArgumentAssignmentResult>
assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount, bool IsVariadic,
const CallingConventionInfo &Convention) {
- auto I64 = LLT::makeInteger(64);
+ auto I64 = LowLevelType::makeCategoryNeutralScalar(64);
auto StackAlign = alignment(Convention.StackArgumentAlignmentBytes);
if (!I64 || !StackAlign)
return makeUnexpected(ErrorCode::InternalError, "RISC-V ABI primitive type facts are invalid");
@@ -325,7 +328,7 @@ assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount
false, false);
} else {
auto View =
- floatingRegisterView(Convention.FloatingArgumentRegisters[State.FPR++], Value.Type);
+ floatingRegisterView(Convention.FloatingArgumentRegisters[State.FPR++], Value);
if (!View)
return std::unexpected(View.error());
Assignment = registerAssignment(Value, Index + Fragment, *View, Value.Type, false, false);
@@ -356,7 +359,7 @@ assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount
const bool HasGPR =
!ForceEntireGroupToStack && State.GPR < Convention.IntegerArgumentRegisters.size();
if (HasGPR) {
- const bool Bitcast = isSupportedFloat(Value.Type);
+ const bool Bitcast = isSupportedFloat(Value);
auto Assignment = registerAssignment(Value, Index + Fragment,
Convention.IntegerArgumentRegisters[State.GPR++], *I64,
VariadicArgument, Bitcast);
@@ -380,7 +383,7 @@ assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount
if (!AlignedOffset)
return std::unexpected(AlignedOffset.error());
State.StackOffset = *AlignedOffset;
- const LLT LocationType = isSupportedFloat(Value.Type) ? Value.Type : *I64;
+ const LowLevelType LocationType = isSupportedFloat(Value) ? Value.Type : *I64;
auto Assignment = stackAssignment(Value, Index + Fragment, State.StackOffset, LocationType,
VariadicArgument, RequiredAlignment);
if (!Assignment)
@@ -415,7 +418,7 @@ assignReturns(std::span<const ABIValue> Values, bool RequireRegisters,
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V direct returns are limited to two explicit fragments");
}
- auto I64 = LLT::makeInteger(64);
+ auto I64 = LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return std::unexpected(I64.error());
@@ -430,17 +433,17 @@ assignReturns(std::span<const ABIValue> Values, bool RequireRegisters,
"return fragments cannot carry argument-only ABI flags");
}
const bool UseFloatingRegister =
- isSupportedFloat(Value.Type) && FPR < Convention.FloatingReturnRegisters.size();
+ isSupportedFloat(Value) && FPR < Convention.FloatingReturnRegisters.size();
Expected<CCAssignment> Assignment = makeUnexpected(
ErrorCode::Unsupported, "RISC-V calling convention has no return register available");
if (UseFloatingRegister) {
- auto View = floatingRegisterView(Convention.FloatingReturnRegisters[FPR++], Value.Type);
+ auto View = floatingRegisterView(Convention.FloatingReturnRegisters[FPR++], Value);
if (!View)
return std::unexpected(View.error());
Assignment = registerAssignment(Value, Index, *View, Value.Type, false, false);
} else if (GPR < Convention.IntegerReturnRegisters.size()) {
Assignment = registerAssignment(Value, Index, Convention.IntegerReturnRegisters[GPR++], *I64,
- false, isSupportedFloat(Value.Type));
+ false, isSupportedFloat(Value));
}
if (!Assignment)
return std::unexpected(Assignment.error());
@@ -924,8 +927,9 @@ createMemoryOperand(MachineFunction &Function, MemoryAccessFlags Accesses, std::
if (!Info)
return std::unexpected(Info.error());
if (!Info->get().Type || *Info->get().Type != Assignment.ValueType) {
- return makeUnexpected(ErrorCode::VerificationError,
- "call-lowering plan register LLT differs from MachineRegisterInfo");
+ return makeUnexpected(
+ ErrorCode::VerificationError,
+ "call-lowering plan register LowLevelType differs from MachineRegisterInfo");
}
return {};
};
@@ -952,10 +956,12 @@ createMemoryOperand(MachineFunction &Function, MemoryAccessFlags Accesses, std::
auto Info = Registers.virtualRegisterInfo(CalleeReg);
if (!Info)
return std::unexpected(Info.error());
- const std::optional<LLT> Type = Info->get().Type;
- if (!Type || ((!Type->isPointer() && !Type->isInteger()) || Type->scalarBitWidth() != 64)) {
- return makeUnexpected(ErrorCode::VerificationError,
- "indirect RISC-V callee requires a 64-bit pointer or integer LLT");
+ const std::optional<LowLevelType> Type = Info->get().Type;
+ if (!Type || ((!Type->isPointer() && !Type->isCategoryNeutralScalar()) ||
+ Type->scalarBitWidth() != 64)) {
+ return makeUnexpected(
+ ErrorCode::VerificationError,
+ "indirect RISC-V callee requires a 64-bit pointer or integer LowLevelType");
}
}
}
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index a7160b4..e4c937f 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -31,8 +31,8 @@
namespace rcc::riscv {
namespace {
-[[nodiscard]] std::optional<LLT> registerType(const MachineFunction &Function,
- const MachineOperand &Operand) {
+[[nodiscard]] std::optional<LowLevelType> registerType(const MachineFunction &Function,
+ const MachineOperand &Operand) {
const Register *Reg = Operand.getIf<Register>();
if (Reg == nullptr || !Reg->isVirtual())
return std::nullopt;
@@ -42,43 +42,59 @@ namespace {
return Info->get().Type;
}
-[[nodiscard]] std::optional<LLT> resultType(const MachineFunction &Function,
- const MachineInstr &Instruction) {
+[[nodiscard]] std::optional<LowLevelType> resultType(const MachineFunction &Function,
+ const MachineInstr &Instruction) {
const MachineOperand *Result = Instruction.operandAt(0);
return Result == nullptr ? std::nullopt : registerType(Function, *Result);
}
-[[nodiscard]] std::optional<LLT> operandType(const MachineFunction &Function,
- const MachineInstr &Instruction, std::size_t Index) {
+[[nodiscard]] std::optional<LowLevelType>
+operandType(const MachineFunction &Function, const MachineInstr &Instruction, std::size_t Index) {
const MachineOperand *Operand = Instruction.operandAt(Index);
return Operand == nullptr ? std::nullopt : registerType(Function, *Operand);
}
-[[nodiscard]] bool isRVFloatType(LLT Type) noexcept {
- if (!Type.isFloat())
- return false;
- const std::optional<FloatSemantics> Semantics = Type.floatSemantics();
- return Semantics &&
- (*Semantics == FloatSemantics::IEEESingle || *Semantics == FloatSemantics::IEEEDouble);
+[[nodiscard]] bool isSupportedFloatingScalar(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() &&
+ (Type.scalarBitWidth() == 32 || Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isSupportedIntegerType(LLT Type) noexcept {
- return ((Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isSupportedIntegerType(LowLevelType Type) noexcept {
+ return (Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64) ||
(Type.isPointer() && Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isSupportedIntegerScalar(LLT Type) noexcept {
- return (Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isSupportedIntegerScalar(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64;
}
-[[nodiscard]] bool isScalarGPRType(LLT Type) noexcept {
- return ((Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isScalarGPRType(LowLevelType Type) noexcept {
+ return (Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64) ||
(Type.isPointer() && Type.scalarBitWidth() == 64);
}
+[[nodiscard]] constexpr RegisterBankID fprBank() noexcept {
+ return RegisterBankID::fromValue(static_cast<std::uint32_t>(RegisterBank::FPR));
+}
+
+[[nodiscard]] Expected<RegisterBankID> registerBank(const MachineFunction &Function, Register Reg) {
+ if (!Reg.isVirtual()) {
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V generic instruction requires a virtual register");
+ }
+ auto Info = Function.registerInfo().virtualRegisterInfo(Reg);
+ if (!Info)
+ return std::unexpected(Info.error());
+ if (!Info->get().Bank) {
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V instruction selection requires an assigned register bank");
+ }
+ return *Info->get().Bank;
+}
+
[[nodiscard]] bool fitsSigned(std::int64_t Value, std::uint32_t Bits) noexcept {
const std::int64_t Minimum = -(std::int64_t{1} << (Bits - 1U));
const std::int64_t Maximum = (std::int64_t{1} << (Bits - 1U)) - 1;
@@ -146,9 +162,9 @@ public:
const MachineFunction &Function,
const TargetDescription &Target) const override {
if (Instruction.opcode() == instructionOpcode(InstructionOpcode::G_SLLW)) {
- const std::optional<LLT> Type = resultType(Function, Instruction);
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
return Type && Left && Right && isScalarGPRType(*Type) && Type->scalarBitWidth() == 64 &&
*Left == *Type && *Right == *Type
? Expected<void>{}
@@ -158,9 +174,9 @@ public:
if (!isGenericOpcode(Instruction.opcode()))
return {};
const GenericOpcode Generic = static_cast<GenericOpcode>(Instruction.opcode().value());
- const std::optional<LLT> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
const auto Integer = [Type] { return Type && isSupportedIntegerType(*Type); };
- const auto Float = [Type] { return Type && isRVFloatType(*Type); };
+ const auto Float = [Type] { return Type && isSupportedFloatingScalar(*Type); };
auto Classification = Subtarget.getLegalizerInfo()->classify(Instruction, Function, Target);
if (!Classification)
return std::unexpected(Classification.error());
@@ -226,8 +242,7 @@ public:
const MachineOperand *Immediate = Instruction.operandAt(1);
const auto *Floating =
Immediate == nullptr ? nullptr : Immediate->getIf<FloatingImmediateOperand>();
- const std::optional<FloatSemantics> Semantics = Type ? Type->floatSemantics() : std::nullopt;
- if (!Float() || Floating == nullptr || !Semantics || Floating->Bits.semantics() != *Semantics)
+ if (!Float() || Floating == nullptr || Floating->Bits.bitWidth() != Type->scalarBitWidth())
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V selector requires a matching floating constant");
return {};
@@ -240,7 +255,6 @@ public:
case GenericOpcode::G_CONSTANT_FOLD_BARRIER:
case GenericOpcode::G_PTRTOINT:
case GenericOpcode::G_INTTOPTR:
- case GenericOpcode::G_BITCAST:
case GenericOpcode::G_TRUNC:
case GenericOpcode::G_SEXT:
case GenericOpcode::G_SEXT_INREG:
@@ -307,7 +321,7 @@ public:
if (Instruction.opcode() == instructionOpcode(InstructionOpcode::G_SLLW))
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::SLLW));
const GenericOpcode Generic = static_cast<GenericOpcode>(Instruction.opcode().value());
- const std::optional<LLT> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
const auto SelectDirect = [&Instruction](InstructionOpcode Selected) {
return Instruction.setOpcode(instructionOpcode(Selected));
@@ -364,7 +378,7 @@ public:
case GenericOpcode::G_PTRMASK:
return SelectDirect(InstructionOpcode::AND);
case GenericOpcode::G_LOAD:
- return selectLoad(Instruction, Type);
+ return selectLoad(Instruction, Function, Type);
case GenericOpcode::G_SEXTLOAD:
return selectExtLoad(Instruction, Type, true);
case GenericOpcode::G_ZEXTLOAD:
@@ -397,8 +411,6 @@ public:
case GenericOpcode::G_PTRTOINT:
case GenericOpcode::G_INTTOPTR:
return Instruction.setOpcode(opcode(GenericOpcode::COPY));
- case GenericOpcode::G_BITCAST:
- return selectBitcast(Instruction, Function);
case GenericOpcode::G_FADD:
return selectRoundingBinary(Instruction, Type, InstructionOpcode::FADD_S,
InstructionOpcode::FADD_D);
@@ -526,11 +538,17 @@ public:
}
private:
- [[nodiscard]] Expected<Register> createTemporary(MachineFunction &Function, LLT Type,
- const TargetDescription &Target) const {
+ [[nodiscard]] Expected<Register>
+ createTemporary(MachineFunction &Function, LowLevelType Type, const TargetDescription &Target,
+ std::optional<RegisterBankID> Bank = std::nullopt) const {
auto Temporary = Function.registerInfo().createVirtualRegister(Type);
if (!Temporary)
return std::unexpected(Temporary.error());
+ if (Bank) {
+ auto SetBank = Function.registerInfo().setRegisterBank(*Temporary, *Bank);
+ if (!SetBank)
+ return std::unexpected(SetBank.error());
+ }
auto Constraint = RegisterBanks.constrainRegister(Function, *Temporary, Target);
if (!Constraint)
return std::unexpected(Constraint.error());
@@ -624,7 +642,7 @@ private:
[[nodiscard]] Expected<Register> normalizeIntegerBefore(MachineInstr &Anchor,
MachineFunction &Function,
const TargetDescription &Target,
- Register Source, LLT Type,
+ Register Source, LowLevelType Type,
bool Signed) const {
if (!isSupportedIntegerScalar(Type))
return makeUnexpected(ErrorCode::Unsupported,
@@ -689,9 +707,9 @@ private:
[[nodiscard]] Expected<MachineInstr *>
buildGPRSelectAfter(MachineIRBuilder &Builder, MachineInstr &Anchor, MachineFunction &Function,
- const TargetDescription &Target, LLT ValueType, Register Destination,
+ const TargetDescription &Target, LowLevelType ValueType, Register Destination,
Register Condition, Register TrueValue, Register FalseValue) const {
- auto IntegerType = LLT::makeInteger(ValueType.scalarBitWidth());
+ auto IntegerType = LowLevelType::makeCategoryNeutralScalar(ValueType.scalarBitWidth());
if (!IntegerType)
return std::unexpected(IntegerType.error());
auto Mask = createTemporary(Function, *IntegerType, Target);
@@ -725,7 +743,7 @@ private:
[[nodiscard]] Expected<void> selectDivRem(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type, bool Signed) const {
+ std::optional<LowLevelType> Type, bool Signed) const {
const MachineOperand *RemainderOperand = Instruction.operandAt(1);
const MachineOperand *LeftOperand = Instruction.operandAt(2);
const MachineOperand *RightOperand = Instruction.operandAt(3);
@@ -772,7 +790,8 @@ private:
[[nodiscard]] Expected<void> selectMultiplyHigh(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type, bool Signed) const {
+ std::optional<LowLevelType> Type,
+ bool Signed) const {
if (!Type)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V high multiplication has no result type");
@@ -793,7 +812,7 @@ private:
"RISC-V high multiplication has invalid register operands");
const Register DestinationRegister = *Destination;
const Register RightRegister = *Right;
- auto I64 = LLT::makeInteger(64);
+ auto I64 = LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return std::unexpected(I64.error());
auto ExtendedLeft = createTemporary(Function, *I64, Target);
@@ -868,7 +887,7 @@ private:
[[nodiscard]] Expected<void> selectIntegerMinMax(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
GenericOpcode Generic) const {
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *LeftOperand = Instruction.operandAt(1);
@@ -880,7 +899,7 @@ private:
if (!Type || Destination == nullptr || Left == nullptr || Right == nullptr)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V integer min/max has invalid operands");
- auto I1 = LLT::makeInteger(1);
+ auto I1 = LowLevelType::makeCategoryNeutralScalar(1);
if (!I1)
return std::unexpected(I1.error());
auto Condition = createTemporary(Function, *I1, Target);
@@ -922,7 +941,7 @@ private:
[[nodiscard]] Expected<void> selectValue(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type) const {
+ std::optional<LowLevelType> Type) const {
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *ConditionOperand = Instruction.operandAt(1);
const MachineOperand *TrueOperand = Instruction.operandAt(2);
@@ -942,7 +961,7 @@ private:
const Register DestinationRegister = *Destination;
const Register TrueRegister = *TrueValue;
const Register FalseRegister = *FalseValue;
- auto I1 = LLT::makeInteger(1);
+ auto I1 = LowLevelType::makeCategoryNeutralScalar(1);
if (!I1)
return std::unexpected(I1.error());
auto NormalizedCondition = createTemporary(Function, *I1, Target);
@@ -964,8 +983,12 @@ private:
if (!SetNormalize)
return std::unexpected(SetNormalize.error());
+ auto DestinationBank = registerBank(Function, DestinationRegister);
+ if (!DestinationBank)
+ return std::unexpected(DestinationBank.error());
+
MachineIRBuilder Builder(Function, Target);
- if (!Type->isFloat()) {
+ if (*DestinationBank != fprBank()) {
auto Selected =
buildGPRSelectAfter(Builder, Instruction, Function, Target, *Type, DestinationRegister,
*NormalizedCondition, TrueRegister, FalseRegister);
@@ -974,7 +997,7 @@ private:
return {};
}
- auto IntegerType = LLT::makeInteger(Type->scalarBitWidth());
+ auto IntegerType = LowLevelType::makeCategoryNeutralScalar(Type->scalarBitWidth());
if (!IntegerType)
return std::unexpected(IntegerType.error());
auto IntegerTrue = createTemporary(Function, *IntegerType, Target);
@@ -1010,7 +1033,7 @@ private:
[[nodiscard]] Expected<void> selectAbsoluteValue(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type) const {
+ std::optional<LowLevelType> Type) const {
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *SourceOperand = Instruction.operandAt(1);
const Register *Destination =
@@ -1059,12 +1082,13 @@ private:
[[nodiscard]] Expected<std::pair<Register, MachineInstr *>>
buildSignedOverflowAfter(MachineIRBuilder &Builder, MachineInstr &Anchor,
- MachineFunction &Function, const TargetDescription &Target, LLT Type,
- Register Result, Register Left, Register Right, bool IsAdd) const {
+ MachineFunction &Function, const TargetDescription &Target,
+ LowLevelType Type, Register Result, Register Left, Register Right,
+ bool IsAdd) const {
auto FirstDifference = createTemporary(Function, Type, Target);
auto SecondDifference = createTemporary(Function, Type, Target);
auto SignBits = createTemporary(Function, Type, Target);
- auto I1 = LLT::makeInteger(1);
+ auto I1 = LowLevelType::makeCategoryNeutralScalar(1);
if (!I1)
return std::unexpected(I1.error());
auto Overflow = createTemporary(Function, *I1, Target);
@@ -1101,7 +1125,7 @@ private:
[[nodiscard]] Expected<void> selectOverflow(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
GenericOpcode Generic) const {
const MachineOperand *ResultOperand = Instruction.operandAt(0);
const MachineOperand *OverflowOperand = Instruction.operandAt(1);
@@ -1183,7 +1207,7 @@ private:
return {};
}
- auto I64 = LLT::makeInteger(64);
+ auto I64 = LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return std::unexpected(I64.error());
auto Zero = physicalRegister(PhysicalRegisterID::X0);
@@ -1305,7 +1329,7 @@ private:
[[nodiscard]] Expected<void> selectExtendedOverflow(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
GenericOpcode Generic) const {
const MachineOperand *ResultOperand = Instruction.operandAt(0);
const MachineOperand *CarryOutOperand = Instruction.operandAt(1);
@@ -1336,7 +1360,7 @@ private:
IsAdd ? (IsWord ? InstructionOpcode::ADDW : InstructionOpcode::ADD)
: (IsWord ? InstructionOpcode::SUBW : InstructionOpcode::SUB);
auto Partial = createTemporary(Function, *Type, Target);
- auto I1 = LLT::makeInteger(1);
+ auto I1 = LowLevelType::makeCategoryNeutralScalar(1);
if (!Partial || !I1)
return std::unexpected(!Partial ? Partial.error() : I1.error());
auto NormalizedCarry = createTemporary(Function, *I1, Target);
@@ -1404,7 +1428,7 @@ private:
[[nodiscard]] Expected<void> selectAtomicRMW(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
GenericOpcode Generic) const {
const MachineOperand *AddressOperand = Instruction.operandAt(1);
const MachineOperand *ValueOperand = Instruction.operandAt(2);
@@ -1484,8 +1508,8 @@ private:
MachineFunction &Function,
const TargetDescription &Target,
GenericOpcode Generic,
- std::optional<LLT> Type) const {
- const std::optional<LLT> SourceType = operandType(Function, Instruction, 1);
+ std::optional<LowLevelType> Type) const {
+ const std::optional<LowLevelType> SourceType = operandType(Function, Instruction, 1);
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *SourceOperand = Instruction.operandAt(1);
const Register *Destination =
@@ -1539,7 +1563,7 @@ private:
[[nodiscard]] Expected<void> selectSignExtendInRegister(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type) const {
+ std::optional<LowLevelType> Type) const {
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *SourceOperand = Instruction.operandAt(1);
const Register *Destination =
@@ -1610,7 +1634,7 @@ private:
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- const std::optional<LLT> LeftType = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> LeftType = operandType(Function, Instruction, 2);
if (Predicate == nullptr || Predicate->integerPredicate() == nullptr ||
Destination == nullptr || Left == nullptr || Right == nullptr || !LeftType)
return makeUnexpected(ErrorCode::VerificationError,
@@ -1779,8 +1803,8 @@ private:
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- const std::optional<LLT> FloatType = operandType(Function, Instruction, 2);
- const std::optional<LLT> ResultType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> FloatType = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> ResultType = resultType(Function, Instruction);
if (Predicate == nullptr || Predicate->floatingPredicate() == nullptr ||
Destination == nullptr || Left == nullptr || Right == nullptr || !FloatType || !ResultType)
return makeUnexpected(ErrorCode::VerificationError,
@@ -1951,8 +1975,9 @@ private:
[[nodiscard]] Expected<void> selectFloatToInteger(MachineInstr &Instruction,
MachineFunction &Function,
- std::optional<LLT> Type, bool Unsigned) const {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ std::optional<LowLevelType> Type,
+ bool Unsigned) const {
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
if (!Type || !Source)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V floating-to-integer conversion has invalid types");
@@ -1973,8 +1998,9 @@ private:
[[nodiscard]] Expected<void> selectIntegerToFloat(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type, bool Unsigned) const {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ std::optional<LowLevelType> Type,
+ bool Unsigned) const {
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
const MachineOperand *SourceOperand = Instruction.operandAt(1);
const Register *SourceRegister =
SourceOperand == nullptr ? nullptr : SourceOperand->getIf<Register>();
@@ -2003,12 +2029,12 @@ private:
}
[[nodiscard]] Expected<void> selectFloatingMinMax(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode Single,
InstructionOpcode Double) const {
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 32)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 32)
return Instruction.setOpcode(instructionOpcode(Single));
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 64)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 64)
return Instruction.setOpcode(instructionOpcode(Double));
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V cannot select this floating min/max type");
@@ -2068,40 +2094,20 @@ private:
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::EBREAK));
}
- [[nodiscard]] Expected<void> selectBitcast(MachineInstr &Instruction,
- MachineFunction &Function) const {
- const std::optional<LLT> DestinationType = resultType(Function, Instruction);
- const std::optional<LLT> SourceType = operandType(Function, Instruction, 1);
- if (!DestinationType || !SourceType)
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V bitcast has invalid register types");
- if (DestinationType->isInteger() && SourceType->isFloat()) {
- return Instruction.setOpcode(instructionOpcode(SourceType->scalarBitWidth() == 32
- ? InstructionOpcode::FMV_X_W
- : InstructionOpcode::FMV_X_D));
- }
- if (DestinationType->isFloat() && SourceType->isInteger()) {
- return Instruction.setOpcode(instructionOpcode(DestinationType->scalarBitWidth() == 32
- ? InstructionOpcode::FMV_W_X
- : InstructionOpcode::FMV_D_X));
- }
- return makeUnexpected(ErrorCode::Unsupported, "RISC-V bitcast pair is unsupported");
- }
-
[[nodiscard]] Expected<void> selectIntegerBinary(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode DoubleWord,
InstructionOpcode Word) const {
if (!Type || !isSupportedIntegerType(*Type))
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V integer instruction requires a supported scalar integer");
- const bool IsWord = Type->isInteger() && Type->scalarBitWidth() <= 32;
+ const bool IsWord = Type->isCategoryNeutralScalar() && Type->scalarBitWidth() <= 32;
return Instruction.setOpcode(instructionOpcode(IsWord ? Word : DoubleWord));
}
[[nodiscard]] Expected<void>
selectNormalizedIntegerBinary(MachineInstr &Instruction, MachineFunction &Function,
- const TargetDescription &Target, std::optional<LLT> Type,
+ const TargetDescription &Target, std::optional<LowLevelType> Type,
InstructionOpcode DoubleWord, InstructionOpcode Word, bool Signed,
bool NormalizeRight) const {
const MachineOperand *LeftOperand = Instruction.operandAt(1);
@@ -2134,8 +2140,8 @@ private:
return Instruction.setOpcode(instructionOpcode(IsWord ? Word : DoubleWord));
}
- [[nodiscard]] Expected<void> selectLoad(MachineInstr &Instruction,
- std::optional<LLT> Type) const {
+ [[nodiscard]] Expected<void> selectLoad(MachineInstr &Instruction, MachineFunction &Function,
+ std::optional<LowLevelType> Type) const {
if (!Type)
return makeUnexpected(ErrorCode::VerificationError,
"load result has no virtual-register type");
@@ -2143,8 +2149,16 @@ private:
if (!Bytes)
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V load size does not match its result type");
+ const MachineOperand *DestinationOperand = Instruction.operandAt(0);
+ const Register *Destination =
+ DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
+ if (Destination == nullptr)
+ return makeUnexpected(ErrorCode::VerificationError, "RISC-V load has no destination");
+ auto Bank = registerBank(Function, *Destination);
+ if (!Bank)
+ return std::unexpected(Bank.error());
if (Instruction.memOperands().front()->isAtomic()) {
- if (!isSupportedIntegerType(*Type) || (*Bytes != 4 && *Bytes != 8))
+ if (*Bank == fprBank() || !isSupportedIntegerType(*Type) || (*Bytes != 4 && *Bytes != 8))
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V atomic load requires a 32-bit or 64-bit GPR value");
return Instruction.setOpcode(
@@ -2153,7 +2167,7 @@ private:
auto AppendOffset = appendImmediate(Instruction, 0);
if (!AppendOffset)
return std::unexpected(AppendOffset.error());
- if (isSupportedIntegerType(*Type)) {
+ if (*Bank != fprBank() && isSupportedIntegerType(*Type)) {
const InstructionOpcode Selected = *Bytes == 1 ? InstructionOpcode::LB
: *Bytes == 2 ? InstructionOpcode::LH
: *Bytes == 4 ? InstructionOpcode::LW
@@ -2163,15 +2177,15 @@ private:
return makeUnexpected(ErrorCode::Unsupported, "RISC-V integer load width is unsupported");
return Instruction.setOpcode(instructionOpcode(Selected));
}
- if (Type->isFloat() && Type->scalarBitWidth() == 32)
+ if (*Bank == fprBank() && Type->scalarBitWidth() == 32 && *Bytes == 4)
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FLW));
- if (Type->isFloat() && Type->scalarBitWidth() == 64)
+ if (*Bank == fprBank() && Type->scalarBitWidth() == 64 && *Bytes == 8)
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FLD));
return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this generic load type");
}
- [[nodiscard]] Expected<void> selectExtLoad(MachineInstr &Instruction, std::optional<LLT> Type,
- bool Signed) const {
+ [[nodiscard]] Expected<void> selectExtLoad(MachineInstr &Instruction,
+ std::optional<LowLevelType> Type, bool Signed) const {
if (!Type || !isSupportedIntegerType(*Type))
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V extension load requires an integer result");
@@ -2201,10 +2215,10 @@ private:
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V floating extension load has no destination register");
const Register DestinationRegister = *Destination;
- auto F32 = LLT::makeFloat(FloatSemantics::IEEESingle);
+ auto F32 = LowLevelType::makeCategoryNeutralScalar(32);
if (!F32)
return std::unexpected(F32.error());
- auto Temporary = createTemporary(Function, *F32, Target);
+ auto Temporary = createTemporary(Function, *F32, Target, fprBank());
if (!Temporary)
return std::unexpected(Temporary.error());
auto SetDestination = Instruction.operandAt(0)->setRegister(*Temporary);
@@ -2233,10 +2247,10 @@ private:
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V floating truncation store has no value register");
const Register ValueRegister = *Value;
- auto F32 = LLT::makeFloat(FloatSemantics::IEEESingle);
+ auto F32 = LowLevelType::makeCategoryNeutralScalar(32);
if (!F32)
return std::unexpected(F32.error());
- auto Temporary = createTemporary(Function, *F32, Target);
+ auto Temporary = createTemporary(Function, *F32, Target, fprBank());
if (!Temporary)
return std::unexpected(Temporary.error());
MachineIRBuilder Builder(Function, Target);
@@ -2270,7 +2284,7 @@ private:
[[nodiscard]] Expected<void> selectStore(MachineInstr &Instruction,
MachineFunction &Function) const {
const MachineOperand *Value = Instruction.operandAt(0);
- const std::optional<LLT> Type =
+ const std::optional<LowLevelType> Type =
Value == nullptr ? std::nullopt : registerType(Function, *Value);
if (!Type)
return makeUnexpected(ErrorCode::VerificationError,
@@ -2279,8 +2293,14 @@ private:
if (!Bytes)
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V store size does not match its value type");
+ const Register *ValueRegister = Value->getIf<Register>();
+ if (ValueRegister == nullptr)
+ return makeUnexpected(ErrorCode::VerificationError, "RISC-V store has no value register");
+ auto Bank = registerBank(Function, *ValueRegister);
+ if (!Bank)
+ return std::unexpected(Bank.error());
if (Instruction.memOperands().front()->isAtomic()) {
- if (!isSupportedIntegerType(*Type) || (*Bytes != 4 && *Bytes != 8))
+ if (*Bank == fprBank() || !isSupportedIntegerType(*Type) || (*Bytes != 4 && *Bytes != 8))
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V atomic store requires a 32-bit or 64-bit GPR value");
auto Zero = physicalRegister(PhysicalRegisterID::X0);
@@ -2295,7 +2315,7 @@ private:
auto AppendOffset = appendImmediate(Instruction, 0);
if (!AppendOffset)
return std::unexpected(AppendOffset.error());
- if (isSupportedIntegerType(*Type)) {
+ if (*Bank != fprBank() && isSupportedIntegerType(*Type)) {
const InstructionOpcode Selected = *Bytes == 1 ? InstructionOpcode::SB
: *Bytes == 2 ? InstructionOpcode::SH
: *Bytes == 4 ? InstructionOpcode::SW
@@ -2305,9 +2325,9 @@ private:
return makeUnexpected(ErrorCode::Unsupported, "RISC-V integer store width is unsupported");
return Instruction.setOpcode(instructionOpcode(Selected));
}
- if (Type->isFloat() && Type->scalarBitWidth() == 32)
+ if (*Bank == fprBank() && Type->scalarBitWidth() == 32 && *Bytes == 4)
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FSW));
- if (Type->isFloat() && Type->scalarBitWidth() == 64)
+ if (*Bank == fprBank() && Type->scalarBitWidth() == 64 && *Bytes == 8)
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FSD));
return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this generic store type");
}
@@ -2335,7 +2355,7 @@ private:
[[nodiscard]] Expected<void> selectIntegerConstant(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type) const {
+ std::optional<LowLevelType> Type) const {
if (!Type || !isSupportedIntegerType(*Type)) {
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V constant selection requires an i1-i64 or pointer result");
@@ -2357,7 +2377,7 @@ private:
const Register Destination = *DestinationValue;
const std::int64_t Value = *ImmediateValue;
const std::uint32_t ImmediateTargetFlags = ImmediateOperand->targetFlags();
- const bool IsWord = Type->isInteger() && Type->scalarBitWidth() <= 32;
+ const bool IsWord = Type->isCategoryNeutralScalar() && Type->scalarBitWidth() <= 32;
const InstructionOpcode AddImmediate =
IsWord ? InstructionOpcode::ADDIW : InstructionOpcode::ADDI;
const InstructionOpcode ShiftLeftImmediate =
@@ -2488,14 +2508,13 @@ private:
[[nodiscard]] Expected<void> selectFloatingConstant(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- std::optional<LLT> Type) const {
- if (!Type || !isRVFloatType(*Type))
+ std::optional<LowLevelType> Type) const {
+ if (!Type || !isSupportedFloatingScalar(*Type))
return makeUnexpected(ErrorCode::Unsupported, "RISC-V floating constant requires f32 or f64");
const MachineOperand *Immediate = Instruction.operandAt(1);
const auto *Floating =
Immediate == nullptr ? nullptr : Immediate->getIf<FloatingImmediateOperand>();
- const std::optional<FloatSemantics> Semantics = Type->floatSemantics();
- if (Floating == nullptr || !Semantics || Floating->Bits.semantics() != *Semantics)
+ if (Floating == nullptr || Floating->Bits.bitWidth() != Type->scalarBitWidth())
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V floating constant has mismatched bit semantics");
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
@@ -2511,7 +2530,7 @@ private:
auto Integer = APInt::fromUnsigned(64, Bits);
if (!Integer)
return std::unexpected(Integer.error());
- auto IntegerType = LLT::makeInteger(64);
+ auto IntegerType = LowLevelType::makeCategoryNeutralScalar(64);
if (!IntegerType)
return std::unexpected(IntegerType.error());
auto Temporary = createTemporary(Function, *IntegerType, Target);
@@ -2564,35 +2583,35 @@ private:
}
[[nodiscard]] Expected<void> selectRoundingBinary(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode Single,
InstructionOpcode Double) const {
auto RoundingMode = appendImmediate(Instruction, 0);
if (!RoundingMode)
return std::unexpected(RoundingMode.error());
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 32)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 32)
return Instruction.setOpcode(instructionOpcode(Single));
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 64)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 64)
return Instruction.setOpcode(instructionOpcode(Double));
return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this floating binary type");
}
[[nodiscard]] Expected<void> selectRoundingTernary(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode Single,
InstructionOpcode Double) const {
return selectRoundingBinary(Instruction, Type, Single, Double);
}
[[nodiscard]] Expected<void> selectRoundingUnary(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode Single,
InstructionOpcode Double) const {
return selectRoundingBinary(Instruction, Type, Single, Double);
}
[[nodiscard]] Expected<void> selectSignInjection(MachineInstr &Instruction,
- std::optional<LLT> Type,
+ std::optional<LowLevelType> Type,
InstructionOpcode Single,
InstructionOpcode Double) const {
const MachineOperand *Source = Instruction.operandAt(1);
@@ -2603,9 +2622,9 @@ private:
auto Duplicate = insertVirtualUse(Instruction, 2, *SourceReg);
if (!Duplicate)
return std::unexpected(Duplicate.error());
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 32)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 32)
return Instruction.setOpcode(instructionOpcode(Single));
- if (Type && Type->isFloat() && Type->scalarBitWidth() == 64)
+ if (Type && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 64)
return Instruction.setOpcode(instructionOpcode(Double));
return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this floating unary type");
}
diff --git a/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index eace5ad..1a29ebf 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -31,7 +31,8 @@
namespace rcc::riscv {
namespace {
-[[nodiscard]] std::optional<LLT> registerType(const MachineFunction &Function, Register Reg) {
+[[nodiscard]] std::optional<LowLevelType> registerType(const MachineFunction &Function,
+ Register Reg) {
if (!Reg.isVirtual())
return std::nullopt;
auto Info = Function.registerInfo().virtualRegisterInfo(Reg);
@@ -40,62 +41,60 @@ namespace {
return Info->get().Type;
}
-[[nodiscard]] std::optional<LLT> registerType(const MachineFunction &Function,
- const MachineOperand &Operand) {
+[[nodiscard]] std::optional<LowLevelType> registerType(const MachineFunction &Function,
+ const MachineOperand &Operand) {
const Register *Reg = Operand.getIf<Register>();
return Reg == nullptr ? std::nullopt : registerType(Function, *Reg);
}
-[[nodiscard]] std::optional<LLT> resultType(const MachineFunction &Function,
- const MachineInstr &Instruction) {
+[[nodiscard]] std::optional<LowLevelType> resultType(const MachineFunction &Function,
+ const MachineInstr &Instruction) {
const MachineOperand *Result = Instruction.operandAt(0);
return Result == nullptr ? std::nullopt : registerType(Function, *Result);
}
-[[nodiscard]] std::optional<LLT> operandType(const MachineFunction &Function,
- const MachineInstr &Instruction, std::size_t Index) {
+[[nodiscard]] std::optional<LowLevelType>
+operandType(const MachineFunction &Function, const MachineInstr &Instruction, std::size_t Index) {
const MachineOperand *Operand = Instruction.operandAt(Index);
return Operand == nullptr ? std::nullopt : registerType(Function, *Operand);
}
-[[nodiscard]] bool isRVFloatType(LLT Type) noexcept {
- if (!Type.isFloat())
- return false;
- const std::optional<FloatSemantics> Semantics = Type.floatSemantics();
- return Semantics &&
- (*Semantics == FloatSemantics::IEEESingle || *Semantics == FloatSemantics::IEEEDouble);
+[[nodiscard]] bool isSupportedFloatingScalar(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() &&
+ (Type.scalarBitWidth() == 32 || Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isSupportedIntegerType(LLT Type) noexcept {
- return ((Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isSupportedIntegerType(LowLevelType Type) noexcept {
+ return (Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64) ||
(Type.isPointer() && Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isSupportedIntegerScalar(LLT Type) noexcept {
- return (Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isSupportedIntegerScalar(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64;
}
-[[nodiscard]] bool isNativeIntegerScalar(LLT Type) noexcept {
- return (Type.isInteger() || Type.isAnyScalar()) &&
+[[nodiscard]] bool isNativeIntegerScalar(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() &&
(Type.scalarBitWidth() == 32 || Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isScalarGPRType(LLT Type) noexcept {
- return ((Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() != 0 &&
+[[nodiscard]] bool isScalarGPRType(LowLevelType Type) noexcept {
+ return (Type.isCategoryNeutralScalar() && Type.scalarBitWidth() != 0 &&
Type.scalarBitWidth() <= 64) ||
(Type.isPointer() && Type.scalarBitWidth() == 64);
}
-[[nodiscard]] bool isI1Type(LLT Type) noexcept {
- return (Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() == 1;
+[[nodiscard]] bool isI1Type(LowLevelType Type) noexcept {
+ return Type.isCategoryNeutralScalar() && Type.scalarBitWidth() == 1;
}
-[[nodiscard]] bool isScalarIntegerExtension(LLT Destination, LLT Source) noexcept {
- return (Destination.isInteger() || Destination.isAnyScalar()) &&
- (Source.isInteger() || Source.isAnyScalar()) && Destination.scalarBitWidth() != 0 &&
- Source.scalarBitWidth() != 0 && Source.scalarBitWidth() < Destination.scalarBitWidth() &&
+[[nodiscard]] bool isScalarIntegerExtension(LowLevelType Destination,
+ LowLevelType Source) noexcept {
+ return Destination.isCategoryNeutralScalar() && Source.isCategoryNeutralScalar() &&
+ Destination.scalarBitWidth() != 0 && Source.scalarBitWidth() != 0 &&
+ Source.scalarBitWidth() < Destination.scalarBitWidth() &&
Destination.scalarBitWidth() <= 64;
}
@@ -394,11 +393,12 @@ wideConstantUnmergePlan(const MachineInstr &Constant, const MachineFunction &Fun
std::uint64_t Value);
[[nodiscard]] Expected<Register> buildBinaryBefore(MachineIRBuilder &Builder, MachineInstr &Anchor,
- GenericOpcode Generic, LLT Type, Register Left,
- Register Right);
+ GenericOpcode Generic, LowLevelType Type,
+ Register Left, Register Right);
[[nodiscard]] Expected<Register> buildUnaryBefore(MachineIRBuilder &Builder, MachineInstr &Anchor,
- GenericOpcode Generic, LLT Type, Register Source);
+ GenericOpcode Generic, LowLevelType Type,
+ Register Source);
[[nodiscard]] Expected<void> eraseInstruction(MachineInstr &Instruction);
@@ -462,7 +462,7 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
const Register *Narrow = NarrowOperand == nullptr ? nullptr : NarrowOperand->getIf<Register>();
const MachineOperand *WideOperand = Truncation->operandAt(1);
const Register *Wide = WideOperand == nullptr ? nullptr : WideOperand->getIf<Register>();
- const std::optional<LLT> WideType =
+ const std::optional<LowLevelType> WideType =
WideOperand == nullptr ? std::nullopt : registerType(Function, *WideOperand);
if (Narrow == nullptr || Wide == nullptr || !Wide->isVirtual() || !WideType ||
*WideType != *DestinationType || singleRegisterUse(Function, *Narrow) != OnlyUse)
@@ -533,7 +533,7 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
if (Destination == nullptr || !Destination->isVirtual() || Immediate == nullptr)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V narrow constant legalization has invalid operands");
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto SetType = Function.registerInfo().setType(*Destination, *Type);
@@ -554,7 +554,8 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
[[nodiscard]] Expected<Register> widenAtomicCompareExchangeSource(MachineInstr &Instruction,
MachineFunction &Function,
MachineIRBuilder &Builder,
- Register Source, LLT WideType) {
+ Register Source,
+ LowLevelType WideType) {
const auto SourceType = registerType(Function, Source);
if (!SourceType)
return makeUnexpected(ErrorCode::VerificationError,
@@ -578,7 +579,7 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
[[nodiscard]] Expected<void> lowerAtomicCompareExchange(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target) {
- const std::optional<LLT> OriginalType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> OriginalType = resultType(Function, Instruction);
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *CompareOperand = Instruction.operandAt(2);
const MachineOperand *NewValueOperand = Instruction.operandAt(3);
@@ -593,7 +594,7 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
"RISC-V narrow compare-exchange has invalid operands");
const Register OriginalDestination = *Destination;
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -610,7 +611,7 @@ narrowAnyExtBinaryPlan(const MachineInstr &Extension, const MachineFunction &Fun
MachineInstr *FoldedExtension = singleRegisterUse(Function, OriginalDestination);
if (FoldedExtension != nullptr && FoldedExtension->opcode() == opcode(GenericOpcode::G_ANYEXT) &&
operandType(Function, *FoldedExtension, 0)
- .transform([](LLT Type) { return Type.scalarBitWidth() == 64; })
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() == 64; })
.value_or(false)) {
const MachineOperand *WideDestinationOperand = FoldedExtension->operandAt(0);
const Register *FoldedDestination =
@@ -668,7 +669,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
const Register *Compare = CompareOperand == nullptr ? nullptr : CompareOperand->getIf<Register>();
const Register *NewValue =
NewValueOperand == nullptr ? nullptr : NewValueOperand->getIf<Register>();
- const std::optional<LLT> ValueType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> ValueType = resultType(Function, Instruction);
if (OldValue == nullptr || Success == nullptr || Address == nullptr || Compare == nullptr ||
NewValue == nullptr || !ValueType || Instruction.memOperands().size() != 1)
return makeUnexpected(ErrorCode::VerificationError,
@@ -727,7 +728,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
[[nodiscard]] Expected<Register> widenIntegerCompareSource(MachineInstr &Instruction,
MachineFunction &Function,
MachineIRBuilder &Builder,
- Register Source, LLT WideType) {
+ Register Source, LowLevelType WideType) {
const auto SourceType = registerType(Function, Source);
if (!SourceType)
return makeUnexpected(ErrorCode::VerificationError,
@@ -751,7 +752,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
const MachineOperand *ExtendedOperand = User->operandAt(0);
const Register *Extended =
ExtendedOperand == nullptr ? nullptr : ExtendedOperand->getIf<Register>();
- const std::optional<LLT> ExtendedType =
+ const std::optional<LowLevelType> ExtendedType =
ExtendedOperand == nullptr ? std::nullopt : registerType(Function, *ExtendedOperand);
if (Extended == nullptr || !ExtendedType || *ExtendedType != WideType ||
(Def == nullptr || (Def->opcode() != opcode(GenericOpcode::G_CONSTANT) &&
@@ -778,7 +779,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
Def->operandCount() == 2) {
const MachineOperand *WideOperand = Def->operandAt(1);
const Register *WideSource = WideOperand == nullptr ? nullptr : WideOperand->getIf<Register>();
- const std::optional<LLT> ExistingWideType =
+ const std::optional<LowLevelType> ExistingWideType =
WideOperand == nullptr ? std::nullopt : registerType(Function, *WideOperand);
if (WideSource != nullptr && ExistingWideType && *ExistingWideType == WideType) {
auto Result = Function.registerInfo().createVirtualRegister(WideType);
@@ -825,7 +826,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
const Register OriginalLeft = *Left;
const Register OriginalRight = *Right;
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -855,7 +856,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
FoldedExtension->opcode() == opcode(GenericOpcode::G_SEXT) ||
FoldedExtension->opcode() == opcode(GenericOpcode::G_ZEXT)) &&
operandType(Function, *FoldedExtension, 0)
- .transform([](LLT Type) { return Type.scalarBitWidth() == 64; })
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() == 64; })
.value_or(false)) {
const MachineOperand *ExtendedOperand = FoldedExtension->operandAt(0);
const Register *Extended =
@@ -923,7 +924,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
const std::uint64_t Mask = Plan->SourceWidth == 64
? std::numeric_limits<std::uint64_t>::max()
: (std::uint64_t{1} << Plan->SourceWidth) - 1U;
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -964,7 +965,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
if (Plan->SourceWidth == 32 &&
(Plan->Generic == GenericOpcode::G_ADD || Plan->Generic == GenericOpcode::G_SUB)) {
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
auto Temporary = Function.registerInfo().createVirtualRegister(*WideType);
@@ -1043,7 +1044,7 @@ lowerAtomicCompareExchangeWithSuccess(MachineInstr &Instruction, MachineFunction
if (!PoolIndex)
return std::unexpected(PoolIndex.error());
- auto PointerType = LLT::makePointer(0, 64);
+ auto PointerType = LowLevelType::makePointer(0, 64);
if (!PointerType)
return std::unexpected(PointerType.error());
auto Address = Function.registerInfo().createVirtualRegister(*PointerType);
@@ -1143,11 +1144,11 @@ memoryAccessBytes(const MachineInstr &Instruction) noexcept {
return Description.Size.minimumBytes();
}
-[[nodiscard]] bool memoryMatchesType(const MachineInstr &Instruction, LLT Type) noexcept {
+[[nodiscard]] bool memoryMatchesType(const MachineInstr &Instruction, LowLevelType Type) noexcept {
const auto Bytes = memoryAccessBytes(Instruction);
- if (!Bytes || (!isSupportedIntegerType(Type) && !isRVFloatType(Type)))
+ if (!Bytes || (!isSupportedIntegerType(Type) && !isSupportedFloatingScalar(Type)))
return false;
- if (isRVFloatType(Type))
+ if (isSupportedFloatingScalar(Type))
return Type.scalarBitWidth() == 32 ? *Bytes == 4 : *Bytes == 8;
const std::uint64_t ValueBytes = (Type.scalarBitWidth() + 7U) / 8U;
return (*Bytes == 1 || *Bytes == 2 || *Bytes == 4 || *Bytes == 8) && *Bytes <= ValueBytes;
@@ -1224,7 +1225,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
MachineInstr &Anchor,
std::uint32_t Width,
std::uint64_t Value) {
- auto Type = LLT::makeAnyScalar(Width);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(Width);
if (!Type)
return std::unexpected(Type.error());
auto Result = Builder.function().registerInfo().createVirtualRegister(*Type);
@@ -1250,7 +1251,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
}
[[nodiscard]] Expected<Register> buildUnaryBefore(MachineIRBuilder &Builder, MachineInstr &Anchor,
- GenericOpcode Generic, LLT Type,
+ GenericOpcode Generic, LowLevelType Type,
Register Source) {
auto Result = Builder.function().registerInfo().createVirtualRegister(Type);
if (!Result)
@@ -1272,8 +1273,8 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
}
[[nodiscard]] Expected<Register> buildBinaryBefore(MachineIRBuilder &Builder, MachineInstr &Anchor,
- GenericOpcode Generic, LLT Type, Register Left,
- Register Right) {
+ GenericOpcode Generic, LowLevelType Type,
+ Register Left, Register Right) {
auto Result = Builder.function().registerInfo().createVirtualRegister(Type);
if (!Result)
return std::unexpected(Result.error());
@@ -1321,7 +1322,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
[[nodiscard]] Expected<void> widenNarrowMultiply(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target) {
- const std::optional<LLT> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *LeftOperand = Instruction.operandAt(1);
const MachineOperand *RightOperand = Instruction.operandAt(2);
@@ -1342,7 +1343,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
return foldNarrowAnyExtBinary(*Extension, Function, Target);
}
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -1365,7 +1366,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
const TargetDescription &Target,
CallingConvention Convention,
const TargetCallLowering &CallLowering) {
- const std::optional<LLT> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const MachineOperand *LeftOperand = Instruction.operandAt(1);
const MachineOperand *RightOperand = Instruction.operandAt(2);
@@ -1387,6 +1388,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
return ABIValue{
.Value = Reg,
.Type = Type,
+ .Category = ABIValueCategory::Integer,
.OriginalValue = Number,
.FragmentIndex = 0,
.FragmentCount = 1,
@@ -1488,7 +1490,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
}
}
}
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
return buildUnaryBefore(Builder, Anchor, GenericOpcode::G_ZEXT, *WideType, Source);
@@ -1562,7 +1564,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
[[nodiscard]] Expected<void> lowerMergeValues(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target) {
- const std::optional<LLT> DestinationType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> DestinationType = resultType(Function, Instruction);
if (!DestinationType || DestinationType->scalarBitWidth() == 0)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V merge destination has no scalar type");
@@ -1582,7 +1584,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
MachineInstr *Use = singleUseInstruction(Function, *Destination);
if (Use != nullptr && Use->opcode() == opcode(GenericOpcode::G_ZEXT) &&
operandType(Function, *Use, 0)
- .transform([](LLT Type) { return Type.scalarBitWidth() == 64; })
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() == 64; })
.value_or(false)) {
const MachineOperand *ExtendedOperand = Use->operandAt(0);
const Register *Extended =
@@ -1594,7 +1596,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
}
}
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -1613,7 +1615,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
Terms.push_back(*WideSource);
continue;
}
- const std::optional<LLT> SourceType = registerType(Function, *Operand);
+ const std::optional<LowLevelType> SourceType = registerType(Function, *Operand);
if (!SourceType)
return makeUnexpected(ErrorCode::VerificationError, "RISC-V merge source has no scalar type");
const std::uint64_t Shift =
@@ -1758,8 +1760,8 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V unmerge has invalid register operands");
const std::size_t OutputCount = Instruction.operandCount() - 1U;
- const std::optional<LLT> OutputType = operandType(Function, Instruction, 0);
- const std::optional<LLT> SourceType = operandType(Function, Instruction, OutputCount);
+ const std::optional<LowLevelType> OutputType = operandType(Function, Instruction, 0);
+ const std::optional<LowLevelType> SourceType = operandType(Function, Instruction, OutputCount);
if (!OutputType || !SourceType)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V unmerge operands have no scalar types");
@@ -1770,7 +1772,7 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
const Register *Source = SourceOperand == nullptr ? nullptr : SourceOperand->getIf<Register>();
if (Source == nullptr)
return makeUnexpected(ErrorCode::VerificationError, "RISC-V unmerge source is not a register");
- auto WideType = LLT::makeAnyScalar(64);
+ auto WideType = LowLevelType::makeCategoryNeutralScalar(64);
if (!WideType)
return std::unexpected(WideType.error());
MachineIRBuilder Builder(Function, Target);
@@ -1794,11 +1796,11 @@ void eraseDeadArtifacts(std::span<MachineInstr *const> Candidates,
}
MachineInstr *Extension = singleUseInstruction(Function, *Output);
- const bool FoldZExt = Extension != nullptr &&
- Extension->opcode() == opcode(GenericOpcode::G_ZEXT) &&
- operandType(Function, *Extension, 0)
- .transform([](LLT Type) { return Type.scalarBitWidth() == 64; })
- .value_or(false);
+ const bool FoldZExt =
+ Extension != nullptr && Extension->opcode() == opcode(GenericOpcode::G_ZEXT) &&
+ operandType(Function, *Extension, 0)
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() == 64; })
+ .value_or(false);
if (FoldZExt) {
const MachineOperand *ExtendedOperand = Extension->operandAt(0);
const Register *Extended =
@@ -1851,7 +1853,7 @@ collectWideValueParts(Register Value, MachineFunction &Function, unsigned Depth
const auto Type = registerType(Function, Value);
if (!Type)
return makeUnexpected(ErrorCode::VerificationError, "RISC-V wide value has no scalar type");
- if ((!Type->isInteger() && !Type->isAnyScalar()) || Type->scalarBitWidth() == 0)
+ if (!Type->isCategoryNeutralScalar() || Type->scalarBitWidth() == 0)
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V wide-value decomposition requires an integer scalar");
if (Type->scalarBitWidth() <= 64)
@@ -1869,7 +1871,7 @@ collectWideValueParts(Register Value, MachineFunction &Function, unsigned Depth
for (std::size_t Index = 1; Index < Def->operandCount(); ++Index) {
const MachineOperand *Operand = Def->operandAt(Index);
const Register *Part = Operand == nullptr ? nullptr : Operand->getIf<Register>();
- const std::optional<LLT> PartType =
+ const std::optional<LowLevelType> PartType =
Operand == nullptr ? std::nullopt : registerType(Function, *Operand);
if (Part == nullptr || !PartType || PartType->scalarBitWidth() != 64)
return makeUnexpected(ErrorCode::Unsupported,
@@ -1932,7 +1934,7 @@ struct WideResultPlan final {
for (std::size_t Index = 0; Index < RequiredParts; ++Index) {
const MachineOperand *Operand = Use->operandAt(Index);
const Register *Output = Operand == nullptr ? nullptr : Operand->getIf<Register>();
- const std::optional<LLT> Type =
+ const std::optional<LowLevelType> Type =
Operand == nullptr ? std::nullopt : registerType(Function, *Operand);
if (Output == nullptr || !Type || Type->scalarBitWidth() != 64)
return makeUnexpected(ErrorCode::Unsupported,
@@ -1946,7 +1948,7 @@ struct WideResultPlan final {
MachineInstr &Anchor,
IntegerPredicate Predicate,
Register Left, Register Right) {
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Result = Builder.function().registerInfo().createVirtualRegister(*Type);
@@ -1973,8 +1975,8 @@ struct WideResultPlan final {
}
[[nodiscard]] Expected<Register> buildSelectBefore(MachineIRBuilder &Builder, MachineInstr &Anchor,
- LLT Type, Register Condition, Register TrueValue,
- Register FalseValue) {
+ LowLevelType Type, Register Condition,
+ Register TrueValue, Register FalseValue) {
auto Result = Builder.function().registerInfo().createVirtualRegister(Type);
if (!Result)
return std::unexpected(Result.error());
@@ -2007,7 +2009,7 @@ struct TwoLimbShiftResult final {
emitTwoLimbLeftShiftBody(MachineIRBuilder &Builder, MachineInstr &Anchor, Register Low,
Register High, Register Amount, Register AmountExcess, Register AmountLack,
Register Zero, Register IsShort, Register IsZero) {
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto LowShort = buildBinaryBefore(Builder, Anchor, GenericOpcode::G_SHL, *Type, Low, Amount);
@@ -2042,7 +2044,7 @@ emitTwoLimbLeftShiftBody(MachineIRBuilder &Builder, MachineInstr &Anchor, Regist
[[nodiscard]] Expected<TwoLimbShiftResult> emitTwoLimbLeftShift(MachineIRBuilder &Builder,
MachineInstr &Anchor, Register Low,
Register High, Register Amount) {
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Boundary = buildIntegerConstantBefore(Builder, Anchor, 64, 64);
@@ -2074,7 +2076,7 @@ emitTwoLimbLeftShiftBody(MachineIRBuilder &Builder, MachineInstr &Anchor, Regist
emitLowLimbOfTwoLimbLogicalRightShift(MachineIRBuilder &Builder, MachineInstr &Anchor, Register Low,
Register High, Register Amount, Register Boundary,
Register Zero) {
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto AmountExcess =
@@ -2119,7 +2121,7 @@ emitThreeLimbLeftShift(MachineIRBuilder &Builder, MachineInstr &Anchor,
if (Parts.size() != 3)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V three-limb shift requires exactly three limbs");
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
@@ -2291,7 +2293,7 @@ emitThreeLimbLeftShift(MachineIRBuilder &Builder, MachineInstr &Anchor,
if (Left.size() != Right.size() || Left.size() < 2)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V wide add requires matching multi-limb operands");
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
std::vector<Register> Results;
@@ -2356,7 +2358,7 @@ emitThreeLimbLeftShift(MachineIRBuilder &Builder, MachineInstr &Anchor,
if (Left.size() != Right.size() || Left.size() < 2)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V wide sub requires matching multi-limb operands");
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
std::vector<Register> Results;
@@ -2415,7 +2417,7 @@ emitWideBitwise(MachineIRBuilder &Builder, MachineInstr &Anchor, GenericOpcode G
if (Left.size() != Right.size() || Left.size() < 2)
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V wide bitwise operation requires matching multi-limb operands");
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
std::vector<Register> Results;
@@ -2500,7 +2502,8 @@ emitWideBitwise(MachineIRBuilder &Builder, MachineInstr &Anchor, GenericOpcode G
Truncation->opcode() != opcode(GenericOpcode::G_TRUNC) || Truncation->operandCount() != 2)
return false;
return operandType(Function, *Truncation, 1)
- .transform([](LLT Type) { return isScalarGPRType(Type) && Type.scalarBitWidth() == 64; })
+ .transform(
+ [](LowLevelType Type) { return isScalarGPRType(Type) && Type.scalarBitWidth() == 64; })
.value_or(false);
}
@@ -2515,7 +2518,7 @@ emitWideBitwise(MachineIRBuilder &Builder, MachineInstr &Anchor, GenericOpcode G
const MachineOperand *Definition = Function.registerInfo().getUniqueVRegDef(Condition);
MachineInstr *Truncation = const_cast<MachineInstr *>(Definition->parent());
const Register Source = *Truncation->operandAt(1)->getIf<Register>();
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
MachineIRBuilder Builder(Function, Target);
@@ -2549,7 +2552,7 @@ struct NarrowPhiIncoming final {
[[nodiscard]] Expected<Register>
buildIncomingConversion(MachineFunction &Function, const TargetDescription &Target,
MachineBasicBlock &Block, MachineInstr *Anchor, GenericOpcode Generic,
- LLT Type, Register Source) {
+ LowLevelType Type, Register Source) {
auto Result = Function.registerInfo().createVirtualRegister(Type);
if (!Result)
return std::unexpected(Result.error());
@@ -2573,14 +2576,14 @@ buildIncomingConversion(MachineFunction &Function, const TargetDescription &Targ
[[nodiscard]] Expected<void> lowerNarrowPhi(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target) {
- const std::optional<LLT> OriginalType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> OriginalType = resultType(Function, Instruction);
const MachineOperand *DestinationOperand = Instruction.operandAt(0);
const Register *Destination =
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
if (!OriginalType || Destination == nullptr || OriginalType->scalarBitWidth() >= 32 ||
Instruction.operandCount() < 3 || (Instruction.operandCount() % 2U) == 0)
return makeUnexpected(ErrorCode::VerificationError, "RISC-V narrow PHI has invalid operands");
- auto LegalType = LLT::makeAnyScalar(32);
+ auto LegalType = LowLevelType::makeCategoryNeutralScalar(32);
if (!LegalType)
return std::unexpected(LegalType.error());
@@ -2603,7 +2606,7 @@ buildIncomingConversion(MachineFunction &Function, const TargetDescription &Targ
if (Def != nullptr && Def->opcode() == opcode(GenericOpcode::G_TRUNC) &&
Def->operandCount() == 2 && singleRegisterUse(Function, *Value) == &Instruction &&
operandType(Function, *Def, 1)
- .transform([](LLT Type) { return Type.scalarBitWidth() >= 32; })
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() >= 32; })
.value_or(false)) {
Reusable = Def;
}
@@ -2731,7 +2734,7 @@ buildIncomingConversion(MachineFunction &Function, const TargetDescription &Targ
auto ResultPlan = wideResultPlan(*Destination, Function, PartCount);
if (!ResultPlan)
return std::unexpected(ResultPlan.error());
- auto Type = LLT::makeAnyScalar(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
MachineIRBuilder Builder(Function, Target);
@@ -2800,7 +2803,7 @@ buildIncomingConversion(MachineFunction &Function, const TargetDescription &Targ
if (Trunc == nullptr || Trunc->opcode() != opcode(GenericOpcode::G_TRUNC) ||
Trunc->operandAt(1) != &Use)
return false;
- const std::optional<LLT> Result = resultType(Function, *Trunc);
+ const std::optional<LowLevelType> Result = resultType(Function, *Trunc);
if (!Result || Result->scalarBitWidth() > LowType->scalarBitWidth())
return false;
}
@@ -2813,13 +2816,14 @@ struct RV64ScalarLayout final {
std::uint64_t ABIAlignment = 0;
};
-[[nodiscard]] std::optional<RV64ScalarLayout> rv64ScalarLayout(LLT Type) noexcept {
+[[nodiscard]] std::optional<RV64ScalarLayout> rv64ScalarLayout(LowLevelType Type) noexcept {
if (Type.isPointer()) {
return Type.addressSpace() == 0 && Type.scalarBitWidth() == 64
? std::optional<RV64ScalarLayout>{{8, 8, 8}}
: std::nullopt;
}
- if ((!isSupportedIntegerType(Type) && !isRVFloatType(Type)) || Type.scalarBitWidth() == 0) {
+ if ((!isSupportedIntegerType(Type) && !isSupportedFloatingScalar(Type)) ||
+ Type.scalarBitWidth() == 0) {
return std::nullopt;
}
const std::uint64_t StoreBytes = (Type.scalarBitWidth() + 7U) / 8U;
@@ -2828,7 +2832,7 @@ struct RV64ScalarLayout final {
}
[[nodiscard]] Expected<const MachineMemOperand *>
-createMemoryAccess(MachineFunction &Function, MemoryAccessFlag Access, LLT Type,
+createMemoryAccess(MachineFunction &Function, MemoryAccessFlag Access, LowLevelType Type,
std::uint64_t SizeBytes, std::uint64_t AlignmentBytes) {
auto Size = MemorySize::fixed(SizeBytes);
auto Align = Alignment::create(AlignmentBytes);
@@ -2845,8 +2849,8 @@ createMemoryAccess(MachineFunction &Function, MemoryAccessFlag Access, LLT Type,
struct VAArgPlan final {
Register Destination;
Register ListPointer;
- LLT DestinationType;
- LLT PointerType;
+ LowLevelType DestinationType;
+ LowLevelType PointerType;
std::uint64_t Alignment = 0;
RV64ScalarLayout ValueLayout;
};
@@ -2863,8 +2867,8 @@ struct VAArgPlan final {
const Register *Destination =
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
const Register *ListPointer = ListOperand == nullptr ? nullptr : ListOperand->getIf<Register>();
- const std::optional<LLT> DestinationType = resultType(Function, Instruction);
- const std::optional<LLT> PointerType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> DestinationType = resultType(Function, Instruction);
+ const std::optional<LowLevelType> PointerType = operandType(Function, Instruction, 1);
const auto AlignmentValue = AlignmentOperand == nullptr
? Expected<std::int64_t>(std::unexpected(
Error(ErrorCode::InvalidArgument, "missing alignment")))
@@ -2989,7 +2993,7 @@ struct VAArgPlan final {
struct VACopyPlan final {
Register Destination;
Register Source;
- LLT PointerType;
+ LowLevelType PointerType;
};
[[nodiscard]] std::optional<VACopyPlan> vacopyPlan(const MachineInstr &Instruction,
@@ -3006,8 +3010,8 @@ struct VACopyPlan final {
const Register *Destination =
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
const Register *Source = SourceOperand == nullptr ? nullptr : SourceOperand->getIf<Register>();
- const std::optional<LLT> DestinationType = operandType(Function, Instruction, 1);
- const std::optional<LLT> SourceType = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> DestinationType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> SourceType = operandType(Function, Instruction, 2);
if (Intrinsic == nullptr || Intrinsic->ID != intrinsicID(GenericIntrinsic::VACopy) ||
Destination == nullptr || Source == nullptr || !Destination->isVirtual() ||
!Source->isVirtual() || !DestinationOperand->isUse() || !SourceOperand->isUse() ||
@@ -3095,7 +3099,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
return LegalizationAction::Legal;
const GenericOpcode Generic = static_cast<GenericOpcode>(Instruction.opcode().value());
- const std::optional<LLT> Type = resultType(Function, Instruction);
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
switch (Generic) {
case GenericOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
return vacopyPlan(Instruction, Function) ? LegalizationAction::Custom
@@ -3110,7 +3114,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_BR:
return LegalizationAction::Legal;
case GenericOpcode::G_BRCOND: {
- const std::optional<LLT> Condition = operandType(Function, Instruction, 0);
+ const std::optional<LowLevelType> Condition = operandType(Function, Instruction, 0);
if (!Condition || !isScalarGPRType(*Condition))
return LegalizationAction::Unsupported;
return canLowerNarrowBranchCondition(Instruction, Function) ? LegalizationAction::Custom
@@ -3120,28 +3124,28 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
if (!Type)
return LegalizationAction::Unsupported;
for (std::size_t Index = 1; Index < Instruction.operandCount(); Index += 2) {
- const std::optional<LLT> Incoming = operandType(Function, Instruction, Index);
+ const std::optional<LowLevelType> Incoming = operandType(Function, Instruction, Index);
if (!Incoming || *Incoming != *Type)
return LegalizationAction::Unsupported;
}
- if ((Type->isInteger() || Type->isAnyScalar()) && Type->scalarBitWidth() > 64)
+ if (Type->isCategoryNeutralScalar() && Type->scalarBitWidth() > 64)
return LegalizationAction::Custom;
- if ((Type->isInteger() || Type->isAnyScalar()) && Type->scalarBitWidth() < 32)
+ if (Type->isCategoryNeutralScalar() && Type->scalarBitWidth() < 32)
return LegalizationAction::Custom;
- if (!isSupportedIntegerType(*Type) && !isRVFloatType(*Type))
+ if (!isSupportedIntegerType(*Type))
return LegalizationAction::Unsupported;
return LegalizationAction::Legal;
}
case GenericOpcode::G_IMPLICIT_DEF:
- return Type && (isSupportedIntegerType(*Type) || isRVFloatType(*Type))
- ? LegalizationAction::Legal
- : LegalizationAction::Unsupported;
+ return Type && isSupportedIntegerType(*Type) ? LegalizationAction::Legal
+ : LegalizationAction::Unsupported;
case GenericOpcode::G_STORE:
if (Instruction.operandCount() == 0)
return LegalizationAction::Unsupported;
- if (const std::optional<LLT> ValueType = registerType(Function, *Instruction.operandAt(0));
+ if (const std::optional<LowLevelType> ValueType =
+ registerType(Function, *Instruction.operandAt(0));
ValueType) {
- const std::optional<LLT> AddressType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> AddressType = operandType(Function, Instruction, 1);
if (!AddressType || !AddressType->isPointer() || AddressType->addressSpace() != 0 ||
AddressType->scalarBitWidth() != 64) {
return LegalizationAction::Unsupported;
@@ -3153,8 +3157,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
- if ((isSupportedIntegerType(*ValueType) || isRVFloatType(*ValueType)) &&
- isSupportedNonAtomicMemoryAccess(Instruction) &&
+ if (isSupportedIntegerType(*ValueType) && isSupportedNonAtomicMemoryAccess(Instruction) &&
memoryMatchesType(Instruction, *ValueType)) {
return LegalizationAction::Legal;
}
@@ -3163,7 +3166,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_SEXTLOAD:
case GenericOpcode::G_ZEXTLOAD: {
const auto Bytes = memoryAccessBytes(Instruction);
- const std::optional<LLT> AddressType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> AddressType = operandType(Function, Instruction, 1);
return Type && Bytes && AddressType && isSupportedIntegerType(*Type) &&
AddressType->isPointer() && AddressType->addressSpace() == 0 &&
AddressType->scalarBitWidth() == 64 &&
@@ -3175,19 +3178,19 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_FPEXTLOAD: {
const auto Bytes = memoryAccessBytes(Instruction);
- const std::optional<LLT> AddressType = operandType(Function, Instruction, 1);
- return Type && Bytes && AddressType && Type->isFloat() && Type->scalarBitWidth() == 64 &&
- AddressType->isPointer() && AddressType->addressSpace() == 0 &&
- AddressType->scalarBitWidth() == 64 && *Bytes == 4 &&
- isSupportedNonAtomicMemoryAccess(Instruction)
+ const std::optional<LowLevelType> AddressType = operandType(Function, Instruction, 1);
+ return Type && Bytes && AddressType && Type->isCategoryNeutralScalar() &&
+ Type->scalarBitWidth() == 64 && AddressType->isPointer() &&
+ AddressType->addressSpace() == 0 && AddressType->scalarBitWidth() == 64 &&
+ *Bytes == 4 && isSupportedNonAtomicMemoryAccess(Instruction)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FPTRUNCSTORE: {
- const std::optional<LLT> ValueType = operandType(Function, Instruction, 0);
- const std::optional<LLT> AddressType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> ValueType = operandType(Function, Instruction, 0);
+ const std::optional<LowLevelType> AddressType = operandType(Function, Instruction, 1);
const auto Bytes = memoryAccessBytes(Instruction);
- return ValueType && AddressType && Bytes && ValueType->isFloat() &&
+ return ValueType && AddressType && Bytes && ValueType->isCategoryNeutralScalar() &&
ValueType->scalarBitWidth() == 64 && AddressType->isPointer() &&
AddressType->addressSpace() == 0 && AddressType->scalarBitWidth() == 64 &&
*Bytes == 4 && isSupportedNonAtomicMemoryAccess(Instruction)
@@ -3196,7 +3199,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_LOAD:
if (Type) {
- const std::optional<LLT> AddressType = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> AddressType = operandType(Function, Instruction, 1);
if (!AddressType || !AddressType->isPointer() || AddressType->addressSpace() != 0 ||
AddressType->scalarBitWidth() != 64) {
return LegalizationAction::Unsupported;
@@ -3208,8 +3211,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
- if ((isSupportedIntegerType(*Type) || isRVFloatType(*Type)) &&
- isSupportedNonAtomicMemoryAccess(Instruction) && memoryMatchesType(Instruction, *Type)) {
+ if (isSupportedIntegerType(*Type) && isSupportedNonAtomicMemoryAccess(Instruction) &&
+ memoryMatchesType(Instruction, *Type)) {
return LegalizationAction::Legal;
}
}
@@ -3218,33 +3221,35 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_FSUB:
case GenericOpcode::G_FMUL:
case GenericOpcode::G_FDIV: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
- return Type && Left && Right && isRVFloatType(*Type) && *Left == *Type && *Right == *Type
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
+ return Type && Left && Right && isSupportedFloatingScalar(*Type) && *Left == *Type &&
+ *Right == *Type
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FMA: {
- const std::optional<LLT> First = operandType(Function, Instruction, 1);
- const std::optional<LLT> Second = operandType(Function, Instruction, 2);
- const std::optional<LLT> Third = operandType(Function, Instruction, 3);
- return Type && First && Second && Third && isRVFloatType(*Type) && *First == *Type &&
- *Second == *Type && *Third == *Type
+ const std::optional<LowLevelType> First = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Second = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Third = operandType(Function, Instruction, 3);
+ return Type && First && Second && Third && isSupportedFloatingScalar(*Type) &&
+ *First == *Type && *Second == *Type && *Third == *Type
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FNEG:
case GenericOpcode::G_FABS:
case GenericOpcode::G_FSQRT: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- return Type && Source && isRVFloatType(*Type) && *Source == *Type
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && isSupportedFloatingScalar(*Type) && *Source == *Type
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FCOPYSIGN: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
- return Type && Left && Right && isRVFloatType(*Type) && *Left == *Type && *Right == *Type
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
+ return Type && Left && Right && isSupportedFloatingScalar(*Type) && *Left == *Type &&
+ *Right == *Type
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
@@ -3252,16 +3257,15 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
const MachineOperand *Immediate = Instruction.operandAt(1);
const auto *Floating =
Immediate == nullptr ? nullptr : Immediate->getIf<FloatingImmediateOperand>();
- const std::optional<FloatSemantics> Semantics = Type ? Type->floatSemantics() : std::nullopt;
- return Type && isRVFloatType(*Type) && Floating != nullptr && Semantics &&
- Floating->Bits.semantics() == *Semantics
+ return Type && isSupportedFloatingScalar(*Type) && Floating != nullptr &&
+ Floating->Bits.bitWidth() == Type->scalarBitWidth()
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_ASSERT_SEXT:
case GenericOpcode::G_ASSERT_ZEXT:
case GenericOpcode::G_ASSERT_ALIGN: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
return Type && Source && *Type == *Source && isScalarGPRType(*Type) &&
Instruction.operandCount() == 3
? LegalizationAction::Legal
@@ -3269,38 +3273,35 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_FREEZE:
case GenericOpcode::G_CONSTANT_FOLD_BARRIER: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- return Type && Source && *Type == *Source &&
- (isSupportedIntegerType(*Type) || isRVFloatType(*Type))
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && *Type == *Source && isSupportedIntegerType(*Type)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_PTRTOINT: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- return Type && Source && Type->isInteger() && Type->scalarBitWidth() == 64 &&
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 64 &&
Source->isPointer() && Source->scalarBitWidth() == 64
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_INTTOPTR: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
return Type && Source && Type->isPointer() && Type->scalarBitWidth() == 64 &&
- Source->isInteger() && Source->scalarBitWidth() == 64
+ Source->isCategoryNeutralScalar() && Source->scalarBitWidth() == 64
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_BITCAST: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- const bool IntegerFloatPair =
- Type && Source && Type->scalarBitWidth() == Source->scalarBitWidth() &&
- ((Type->isFloat() && Source->isInteger()) || (Type->isInteger() && Source->isFloat())) &&
- (Type->scalarBitWidth() == 32 || Type->scalarBitWidth() == 64);
- return IntegerFloatPair ? LegalizationAction::Legal : LegalizationAction::Unsupported;
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && *Type != *Source && Type->scalarBitWidth() == Source->scalarBitWidth()
+ ? LegalizationAction::Legal
+ : LegalizationAction::Unsupported;
}
case GenericOpcode::G_ANYEXT:
case GenericOpcode::G_SEXT:
case GenericOpcode::G_ZEXT: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
if (!Type || !Source)
return LegalizationAction::Unsupported;
if (!isScalarIntegerExtension(*Type, *Source)) {
@@ -3309,8 +3310,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
MachineInstr *OnlyUse =
Destination == nullptr ? nullptr : singleUseInstruction(Function, *Destination);
- return (Type->isInteger() || Type->isAnyScalar()) &&
- (Source->isInteger() || Source->isAnyScalar()) &&
+ return Type->isCategoryNeutralScalar() && Source->isCategoryNeutralScalar() &&
Type->scalarBitWidth() > 64 &&
Source->scalarBitWidth() < Type->scalarBitWidth() && OnlyUse != nullptr &&
OnlyUse->opcode() == opcode(GenericOpcode::G_UNMERGE_VALUES)
@@ -3334,10 +3334,9 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
return LegalizationAction::Legal;
}
case GenericOpcode::G_TRUNC: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- if (Type && Source && (Type->isInteger() || Type->isAnyScalar()) &&
- (Source->isInteger() || Source->isAnyScalar()) && Type->scalarBitWidth() > 64 &&
- Source->scalarBitWidth() > Type->scalarBitWidth())
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ if (Type && Source && Type->isCategoryNeutralScalar() && Source->isCategoryNeutralScalar() &&
+ Type->scalarBitWidth() > 64 && Source->scalarBitWidth() > Type->scalarBitWidth())
return LegalizationAction::Legal;
return Type && Source && isSupportedIntegerScalar(*Type) && isSupportedIntegerScalar(*Source) &&
Type->scalarBitWidth() != 0 && Source->scalarBitWidth() >= Type->scalarBitWidth()
@@ -3351,19 +3350,20 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
const std::size_t SmallTypeIndex = Generic == GenericOpcode::G_MERGE_VALUES ? 1 : 0;
const std::size_t BigTypeIndex =
Generic == GenericOpcode::G_MERGE_VALUES ? 0 : Instruction.operandCount() - 1U;
- const std::optional<LLT> SmallType = operandType(Function, Instruction, SmallTypeIndex);
- const std::optional<LLT> BigType = operandType(Function, Instruction, BigTypeIndex);
+ const std::optional<LowLevelType> SmallType =
+ operandType(Function, Instruction, SmallTypeIndex);
+ const std::optional<LowLevelType> BigType = operandType(Function, Instruction, BigTypeIndex);
if (SmallType && BigType && Generic == GenericOpcode::G_MERGE_VALUES &&
BigType->scalarBitWidth() > 64 && !canFoldWideMergeImmediately(Instruction, Function))
return LegalizationAction::Legal;
- return SmallType && BigType && (SmallType->isInteger() || SmallType->isAnyScalar()) &&
- (BigType->isInteger() || BigType->isAnyScalar()) &&
- SmallType->scalarBitWidth() != 0 && BigType->scalarBitWidth() != 0
+ return SmallType && BigType && SmallType->isCategoryNeutralScalar() &&
+ BigType->isCategoryNeutralScalar() && SmallType->scalarBitWidth() != 0 &&
+ BigType->scalarBitWidth() != 0
? LegalizationAction::Custom
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_SEXT_INREG: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
const MachineOperand *WidthOperand = Instruction.operandAt(2);
const auto Width =
WidthOperand == nullptr
@@ -3379,8 +3379,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
const MachineOperand *Predicate = Instruction.operandAt(1);
const auto *IntegerPredicate =
Predicate == nullptr ? nullptr : Predicate->getIf<PredicateOperand>();
- const std::optional<LLT> Left = operandType(Function, Instruction, 2);
- const std::optional<LLT> Right = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 3);
if (!Type || !isSupportedIntegerScalar(*Type) || IntegerPredicate == nullptr ||
IntegerPredicate->integerPredicate() == nullptr || !Left || !Right || *Left != *Right ||
!isSupportedIntegerType(*Left)) {
@@ -3394,19 +3394,20 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
const MachineOperand *Predicate = Instruction.operandAt(1);
const auto *FloatingPredicate =
Predicate == nullptr ? nullptr : Predicate->getIf<PredicateOperand>();
- const std::optional<LLT> Left = operandType(Function, Instruction, 2);
- const std::optional<LLT> Right = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 3);
return Type && isI1Type(*Type) && FloatingPredicate != nullptr &&
FloatingPredicate->floatingPredicate() != nullptr && Left && Right &&
- *Left == *Right && isRVFloatType(*Left)
+ *Left == *Right && isSupportedFloatingScalar(*Left)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FPEXT:
case GenericOpcode::G_FPTRUNC: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
const bool IsExtension = Generic == GenericOpcode::G_FPEXT;
- return Type && Source && isRVFloatType(*Type) && isRVFloatType(*Source) &&
+ return Type && Source && isSupportedFloatingScalar(*Type) &&
+ isSupportedFloatingScalar(*Source) &&
((IsExtension && Source->scalarBitWidth() == 32 &&
Type->scalarBitWidth() == 64) ||
(!IsExtension && Source->scalarBitWidth() == 64 &&
@@ -3416,39 +3417,39 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_FPTOSI:
case GenericOpcode::G_FPTOUI: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- return Type && Source && isSupportedIntegerType(*Type) && isRVFloatType(*Source)
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && isSupportedIntegerType(*Type) && isSupportedFloatingScalar(*Source)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_SITOFP:
case GenericOpcode::G_UITOFP: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
- return Type && Source && isRVFloatType(*Type) && isSupportedIntegerType(*Source)
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
+ return Type && Source && isSupportedFloatingScalar(*Type) && isSupportedIntegerType(*Source)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_FMINNUM:
case GenericOpcode::G_FMAXNUM: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
- return Type && Left && Right && isRVFloatType(*Type) && *Left == *Type && *Right == *Type
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
+ return Type && Left && Right && isSupportedFloatingScalar(*Type) && *Left == *Type &&
+ *Right == *Type
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_SELECT: {
- const std::optional<LLT> Condition = operandType(Function, Instruction, 1);
- const std::optional<LLT> TrueValue = operandType(Function, Instruction, 2);
- const std::optional<LLT> FalseValue = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Condition = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> TrueValue = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> FalseValue = operandType(Function, Instruction, 3);
return Type && Condition && TrueValue && FalseValue && isScalarGPRType(*Condition) &&
- *TrueValue == *Type && *FalseValue == *Type &&
- (isSupportedIntegerType(*Type) || isRVFloatType(*Type))
+ *TrueValue == *Type && *FalseValue == *Type && isSupportedIntegerType(*Type)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_PTRMASK: {
- const std::optional<LLT> Pointer = operandType(Function, Instruction, 1);
- const std::optional<LLT> Mask = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Pointer = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Mask = operandType(Function, Instruction, 2);
return Type && Pointer && Mask && Type->isPointer() && Type->addressSpace() == 0 &&
Type->scalarBitWidth() == 64 && *Pointer == *Type &&
isSupportedIntegerScalar(*Mask) && Mask->scalarBitWidth() == 64
@@ -3456,16 +3457,16 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_ABS: {
- const std::optional<LLT> Source = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Source = operandType(Function, Instruction, 1);
return Type && Source && *Source == *Type && isSupportedIntegerScalar(*Type)
? LegalizationAction::Legal
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_SDIVREM:
case GenericOpcode::G_UDIVREM: {
- const std::optional<LLT> Remainder = operandType(Function, Instruction, 1);
- const std::optional<LLT> Left = operandType(Function, Instruction, 2);
- const std::optional<LLT> Right = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Remainder = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 3);
return Type && Remainder && Left && Right && isSupportedIntegerScalar(*Type) &&
*Remainder == *Type && *Left == *Type && *Right == *Type
? LegalizationAction::Legal
@@ -3473,8 +3474,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_SMULH:
case GenericOpcode::G_UMULH: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
return Type && Left && Right && isNativeIntegerScalar(*Type) && *Left == *Type &&
*Right == *Type
? LegalizationAction::Legal
@@ -3484,8 +3485,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_SMAX:
case GenericOpcode::G_UMIN:
case GenericOpcode::G_UMAX: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
return Type && Left && Right && isSupportedIntegerScalar(*Type) && *Left == *Type &&
*Right == *Type
? LegalizationAction::Legal
@@ -3497,9 +3498,9 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_SSUBO:
case GenericOpcode::G_UMULO:
case GenericOpcode::G_SMULO: {
- const std::optional<LLT> Overflow = operandType(Function, Instruction, 1);
- const std::optional<LLT> Left = operandType(Function, Instruction, 2);
- const std::optional<LLT> Right = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Overflow = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 3);
return Type && Overflow && Left && Right && isNativeIntegerScalar(*Type) &&
isI1Type(*Overflow) && *Left == *Type && *Right == *Type
? LegalizationAction::Legal
@@ -3509,10 +3510,10 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_USUBE:
case GenericOpcode::G_SADDE:
case GenericOpcode::G_SSUBE: {
- const std::optional<LLT> CarryOut = operandType(Function, Instruction, 1);
- const std::optional<LLT> Left = operandType(Function, Instruction, 2);
- const std::optional<LLT> Right = operandType(Function, Instruction, 3);
- const std::optional<LLT> CarryIn = operandType(Function, Instruction, 4);
+ const std::optional<LowLevelType> CarryOut = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> CarryIn = operandType(Function, Instruction, 4);
return Type && CarryOut && Left && Right && CarryIn && isNativeIntegerScalar(*Type) &&
isI1Type(*CarryOut) && isI1Type(*CarryIn) && *Left == *Type && *Right == *Type
? LegalizationAction::Legal
@@ -3528,8 +3529,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_ATOMICRMW_MIN:
case GenericOpcode::G_ATOMICRMW_UMAX:
case GenericOpcode::G_ATOMICRMW_UMIN: {
- const std::optional<LLT> Address = operandType(Function, Instruction, 1);
- const std::optional<LLT> Value = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Address = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Value = operandType(Function, Instruction, 2);
const std::uint64_t Bytes = Type ? Type->scalarBitWidth() / 8U : 0;
return Type && Address && Value && isNativeIntegerScalar(*Type) && *Value == *Type &&
Address->isPointer() && Address->addressSpace() == 0 &&
@@ -3540,11 +3541,11 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_ATOMIC_CMPXCHG: {
- const std::optional<LLT> Address = operandType(Function, Instruction, 1);
- const std::optional<LLT> Compare = operandType(Function, Instruction, 2);
- const std::optional<LLT> NewValue = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> Address = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Compare = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> NewValue = operandType(Function, Instruction, 3);
if (!Type || !Address || !Compare || !NewValue || *Compare != *Type || *NewValue != *Type ||
- (!Type->isInteger() && !Type->isAnyScalar()) ||
+ !Type->isCategoryNeutralScalar() ||
(Type->scalarBitWidth() != 8 && Type->scalarBitWidth() != 16 &&
Type->scalarBitWidth() != 32 && Type->scalarBitWidth() != 64) ||
!Address->isPointer() || Address->addressSpace() != 0 || Address->scalarBitWidth() != 64 ||
@@ -3555,13 +3556,12 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
return Type->scalarBitWidth() == 64 ? LegalizationAction::Legal : LegalizationAction::Custom;
}
case GenericOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
- const std::optional<LLT> Success = operandType(Function, Instruction, 1);
- const std::optional<LLT> Address = operandType(Function, Instruction, 2);
- const std::optional<LLT> Compare = operandType(Function, Instruction, 3);
- const std::optional<LLT> NewValue = operandType(Function, Instruction, 4);
+ const std::optional<LowLevelType> Success = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Address = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Compare = operandType(Function, Instruction, 3);
+ const std::optional<LowLevelType> NewValue = operandType(Function, Instruction, 4);
return Type && Success && Address && Compare && NewValue && isI1Type(*Success) &&
- *Compare == *Type && *NewValue == *Type &&
- (Type->isInteger() || Type->isAnyScalar()) &&
+ *Compare == *Type && *NewValue == *Type && Type->isCategoryNeutralScalar() &&
(Type->scalarBitWidth() == 8 || Type->scalarBitWidth() == 16 ||
Type->scalarBitWidth() == 32 || Type->scalarBitWidth() == 64) &&
Address->isPointer() && Address->addressSpace() == 0 &&
@@ -3605,7 +3605,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
}
case GenericOpcode::G_BRINDIRECT:
return operandType(Function, Instruction, 0)
- .transform([](LLT Value) {
+ .transform([](LowLevelType Value) {
return Value.isPointer() && Value.addressSpace() == 0 &&
Value.scalarBitWidth() == 64;
})
@@ -3629,7 +3629,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
return wideConstantUnmergePlan(Instruction, Function).has_value()
? LegalizationAction::Custom
: LegalizationAction::Unsupported;
- if ((Type->isInteger() || Type->isAnyScalar()) && Type->scalarBitWidth() == 64) {
+ if (Type->isCategoryNeutralScalar() && Type->scalarBitWidth() == 64) {
auto Value = signedImmediate(*Immediate);
if (Value && shouldUseRV64IntegerConstantPool(*Value))
return LegalizationAction::Custom;
@@ -3650,10 +3650,10 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
case GenericOpcode::G_SHL:
case GenericOpcode::G_LSHR:
case GenericOpcode::G_ASHR: {
- const std::optional<LLT> Left = operandType(Function, Instruction, 1);
- const std::optional<LLT> Right = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Left = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Right = operandType(Function, Instruction, 2);
if (!Type || !Left || !Right || *Left != *Type || *Right != *Type ||
- (!Type->isInteger() && !Type->isAnyScalar()))
+ !Type->isCategoryNeutralScalar())
return LegalizationAction::Unsupported;
if (Type->scalarBitWidth() > 64) {
return Generic == GenericOpcode::G_ADD || Generic == GenericOpcode::G_SUB ||
@@ -3670,7 +3670,7 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
MachineInstr *Extension =
Destination == nullptr ? nullptr : singleRegisterUse(Function, *Destination);
- const std::optional<LLT> ExtensionType =
+ const std::optional<LowLevelType> ExtensionType =
Extension == nullptr ? std::nullopt : resultType(Function, *Extension);
if (Extension != nullptr && Extension->opcode() == opcode(GenericOpcode::G_ANYEXT) &&
ExtensionType && ExtensionType->scalarBitWidth() == 64) {
@@ -3682,8 +3682,8 @@ Expected<LegalizationAction> RISCVLegalizerInfo::classify(const MachineInstr &In
: LegalizationAction::Unsupported;
}
case GenericOpcode::G_PTR_ADD: {
- const std::optional<LLT> Pointer = operandType(Function, Instruction, 1);
- const std::optional<LLT> Offset = operandType(Function, Instruction, 2);
+ const std::optional<LowLevelType> Pointer = operandType(Function, Instruction, 1);
+ const std::optional<LowLevelType> Offset = operandType(Function, Instruction, 2);
return Type && Pointer && Offset && Type->isPointer() && Type->addressSpace() == 0 &&
Type->scalarBitWidth() == 64 && *Pointer == *Type &&
isSupportedIntegerScalar(*Offset) && Offset->scalarBitWidth() == 64
@@ -3737,7 +3737,7 @@ Expected<void> RISCVLegalizerInfo::lower(MachineInstr &Instruction, MachineFunct
}
if (Action == LegalizationAction::Custom &&
resultType(Function, Instruction)
- .transform([](LLT Type) { return Type.scalarBitWidth() > 64; })
+ .transform([](LowLevelType Type) { return Type.scalarBitWidth() > 64; })
.value_or(false)) {
const Opcode Value = Instruction.opcode();
if (Value == opcode(GenericOpcode::G_ADD) || Value == opcode(GenericOpcode::G_SUB) ||
@@ -3783,8 +3783,8 @@ Expected<void> RISCVLegalizerInfo::lower(MachineInstr &Instruction, MachineFunct
if (Action == LegalizationAction::Custom &&
Instruction.opcode() == opcode(GenericOpcode::G_CONSTANT)) {
const MachineOperand *Immediate = Instruction.operandAt(1);
- const std::optional<LLT> Type = resultType(Function, Instruction);
- if (Immediate != nullptr && Type && (Type->isInteger() || Type->isAnyScalar()) &&
+ const std::optional<LowLevelType> Type = resultType(Function, Instruction);
+ if (Immediate != nullptr && Type && Type->isCategoryNeutralScalar() &&
Type->scalarBitWidth() == 64) {
auto Value = signedImmediate(*Immediate);
if (Value && shouldUseRV64IntegerConstantPool(*Value))
diff --git a/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index 7c60219..66a3371 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -20,13 +20,9 @@
namespace rcc::riscv {
namespace {
-[[nodiscard]] bool isRVFloatType(LLT Type) noexcept {
- return Type.isFloat() && (Type.scalarBitWidth() == 32 || Type.scalarBitWidth() == 64);
-}
-
-[[nodiscard]] bool isScalarGPRType(LLT Type) noexcept {
+[[nodiscard]] bool isScalarGPRType(LowLevelType Type) noexcept {
return (Type.isPointer() && Type.addressSpace() == 0 && Type.scalarBitWidth() == 64) ||
- ((Type.isInteger() || Type.isAnyScalar()) && Type.scalarBitWidth() >= 1 &&
+ (Type.isCategoryNeutralScalar() && Type.scalarBitWidth() >= 1 &&
Type.scalarBitWidth() <= 64);
}
@@ -219,9 +215,9 @@ requiredBankForRegister(const MachineFunction &Function, Register Reg,
"RISC-V selection requires a type for every virtual register");
}
const VirtualRegisterInfo &RegisterInfo = Info->get();
- const LLT Type = RegisterInfo.Type.value_or(LLT{});
+ const LowLevelType Type = RegisterInfo.Type.value_or(LowLevelType{});
RegisterClassID RequiredClass;
- if ((RegisterInfo.Bank && *RegisterInfo.Bank == fprBank()) || Type.isFloat()) {
+ if (RegisterInfo.Bank && *RegisterInfo.Bank == fprBank()) {
if (Type.scalarBitWidth() != 32 && Type.scalarBitWidth() != 64) {
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V RV64GC has no floating register class for type '" +
@@ -269,8 +265,7 @@ RISCVRegisterBankInfo::selectBank(const MachineFunction &Function, Register Reg,
if (!Required)
return std::unexpected(Required.error());
const bool IsConstrained = Required->has_value() || Info.Bank.has_value();
- const RegisterBankID Selected =
- Required->value_or(isRVFloatType(*Info.Type) ? fprBank() : gprBank());
+ const RegisterBankID Selected = Required->value_or(gprBank());
if (Info.Bank && *Info.Bank != Selected) {
return makeUnexpected(ErrorCode::VerificationError,
"RISC-V virtual register has a conflicting register bank");
diff --git a/backend/lib/Target/RISCV/RISCV.rccdesc b/backend/lib/Target/RISCV/RISCV.rccdesc
index 910ea3f..91cad89 100644
--- a/backend/lib/Target/RISCV/RISCV.rccdesc
+++ b/backend/lib/Target/RISCV/RISCV.rccdesc
@@ -1923,7 +1923,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -1941,7 +1941,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -1959,7 +1959,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -1977,7 +1977,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -1994,7 +1994,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2011,7 +2011,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2028,7 +2028,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2045,7 +2045,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_DIV
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2061,7 +2061,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_SQRT
encoding_category: R
assembly_format: FRD_FRS1_RM
@@ -2121,7 +2121,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2
@@ -2136,7 +2136,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2
@@ -2152,7 +2152,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2168,7 +2168,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2184,7 +2184,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2200,7 +2200,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2229,7 +2229,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2244,7 +2244,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2259,7 +2259,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2289,7 +2289,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2305,7 +2305,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2321,7 +2321,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2337,7 +2337,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2399,7 +2399,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -2417,7 +2417,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -2435,7 +2435,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -2453,7 +2453,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R4
assembly_format: FRD_FRS1_FRS2_FRS3_RM
@@ -2470,7 +2470,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2487,7 +2487,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2504,7 +2504,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_MUL
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2521,7 +2521,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_DIV
encoding_category: R
assembly_format: FRD_FRS1_FRS2_RM
@@ -2537,7 +2537,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_SQRT
encoding_category: R
assembly_format: FRD_FRS1_RM
@@ -2597,7 +2597,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2
@@ -2612,7 +2612,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: FRD_FRS1_FRS2
@@ -2628,7 +2628,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2644,7 +2644,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2660,7 +2660,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2676,7 +2676,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: RD_FRS1_RM
@@ -2705,7 +2705,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2720,7 +2720,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2735,7 +2735,7 @@ instructions:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS2 }
num_explicit_defs: 1
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_ADD
encoding_category: R
assembly_format: RD_FRS1_FRS2
@@ -2797,7 +2797,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2813,7 +2813,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_RS1_RM
@@ -2843,7 +2843,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_FRS1_RM
@@ -3373,7 +3373,7 @@ instructions:
- { kinds: [immediate], immediate_predicate: RM, name: RM }
num_explicit_defs: 1
allow_extra_implicit_operands: true
- flags: [produces_code]
+ flags: [may_raise_fp_exception, produces_code]
scheduling_class: FP_CONVERT
encoding_category: R
assembly_format: FRD_FRS1_RM
diff --git a/backend/lib/Target/RISCV/RISCVPseudoExpansion.cpp b/backend/lib/Target/RISCV/RISCVPseudoExpansion.cpp
index d5d932c..b9cdb48 100644
--- a/backend/lib/Target/RISCV/RISCVPseudoExpansion.cpp
+++ b/backend/lib/Target/RISCV/RISCVPseudoExpansion.cpp
@@ -45,7 +45,8 @@ registerBank(Register Reg, const MachineFunction &Function, const TargetDescript
return std::nullopt;
}
-[[nodiscard]] std::optional<LLT> registerType(Register Reg, const MachineFunction &Function) {
+[[nodiscard]] std::optional<LowLevelType> registerType(Register Reg,
+ const MachineFunction &Function) {
if (!Reg.isVirtual())
return std::nullopt;
auto Info = Function.registerInfo().virtualRegisterInfo(Reg);
@@ -156,7 +157,7 @@ copyRegisters(const MachineInstr &Instruction) {
const auto DestinationType = registerType(Registers->first, Function);
const auto SourceType = registerType(Registers->second, Function);
- const std::optional<LLT> Type = DestinationType ? DestinationType : SourceType;
+ const std::optional<LowLevelType> Type = DestinationType ? DestinationType : SourceType;
if (!Type || Type->isVector() || (Type->scalarBitWidth() != 32 && Type->scalarBitWidth() != 64)) {
return makeUnexpected(ErrorCode::Unsupported,
"RISC-V cross-bank COPY requires a scalar 32-bit or 64-bit type");
diff --git a/backend/lib/Tooling/MIRFuzzer.cpp b/backend/lib/Tooling/MIRFuzzer.cpp
index 467291c..dc6b8d1 100644
--- a/backend/lib/Tooling/MIRFuzzer.cpp
+++ b/backend/lib/Tooling/MIRFuzzer.cpp
@@ -186,7 +186,7 @@ private:
MachineBasicBlock *Block = Function->firstBlock();
if (Block == nullptr)
return false;
- auto Type = LLT::makeInteger(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Register = Function->registerInfo().createVirtualRegister(*Type);
diff --git a/backend/unittests/CodeGen/CoreTypesTest.cpp b/backend/unittests/CodeGen/CoreTypesTest.cpp
index b19d6b4..8ad0ce6 100644
--- a/backend/unittests/CodeGen/CoreTypesTest.cpp
+++ b/backend/unittests/CodeGen/CoreTypesTest.cpp
@@ -5,12 +5,10 @@
#include "rcc/CodeGen/Register.h"
#include "rcc/CodeGen/StableID.h"
-#include <array>
#include <cstdint>
#include <iostream>
#include <string_view>
#include <type_traits>
-#include <unordered_set>
namespace {
@@ -32,126 +30,92 @@ private:
};
void testLowLevelTypes(TestContext &Context) {
- const rcc::LLT Invalid;
- Context.expect(!Invalid.isValid(), "default LLT must be invalid");
- Context.expect(Invalid.toString() == "LLT_invalid", "invalid LLT spelling must be stable");
-
- const rcc::LLT Token = rcc::LLT::token();
- Context.expect(Token.isToken(), "token LLT must preserve its kind");
- Context.expect(Token.scalarBitWidth() == 0, "token LLT must have no bit width");
- Context.expect(Token.toString() == "s0", "token LLT must use the MIR token spelling");
-
- auto Any = rcc::LLT::makeAnyScalar(3);
- auto Integer = rcc::LLT::makeInteger(3);
- Context.expect(Any && Integer, "arbitrary positive scalar widths must be accepted");
- if (Any && Integer) {
- Context.expect(Any->isAnyScalar(), "bag-of-bits LLT must preserve its kind");
- Context.expect(Integer->isInteger(), "integer LLT must preserve its kind");
- Context.expect(*Any != *Integer, "bag-of-bits and integer LLTs must remain distinct");
- Context.expect(Any->toString() == "s3", "bag-of-bits LLT spelling must include its width");
- Context.expect(Integer->toString() == "i3", "integer LLT spelling must include its width");
+ const rcc::LowLevelType Invalid;
+ Context.expect(!Invalid.isValid(), "default LowLevelType must be invalid");
+ Context.expect(Invalid.toString() == "LLT_invalid",
+ "invalid LowLevelType spelling must be stable");
+
+ const rcc::LowLevelType Token = rcc::LowLevelType::token();
+ Context.expect(Token.isToken(), "token LowLevelType must preserve its kind");
+ Context.expect(Token.scalarBitWidth() == 0, "token LowLevelType must have no bit width");
+ Context.expect(Token.toString() == "s0", "token LowLevelType must use the MIR token spelling");
+
+ auto Scalar = rcc::LowLevelType::makeCategoryNeutralScalar(3);
+ auto SameScalar = rcc::LowLevelType::makeCategoryNeutralScalar(3);
+ Context.expect(Scalar && SameScalar, "arbitrary positive scalar widths must be accepted");
+ if (Scalar && SameScalar) {
+ Context.expect(Scalar->isCategoryNeutralScalar(),
+ "scalar LowLevelType must preserve its category-neutral kind");
+ Context.expect(*Scalar == *SameScalar,
+ "equal-width scalars must have one canonical low-level type");
+ Context.expect(Scalar->toString() == "s3",
+ "scalar LowLevelType spelling must include its width");
}
- Context.expect(!rcc::LLT::makeInteger(0), "zero-width integer LLT must be rejected");
- Context.expect(!rcc::LLT::makeInteger(std::uint64_t{1} << 16),
- "integer LLT wider than the encoding must be rejected");
-
- constexpr std::array FloatCases{
- std::pair{rcc::FloatSemantics::IEEEHalf, std::uint32_t{16}},
- std::pair{rcc::FloatSemantics::BFloat, std::uint32_t{16}},
- std::pair{rcc::FloatSemantics::IEEESingle, std::uint32_t{32}},
- std::pair{rcc::FloatSemantics::IEEEDouble, std::uint32_t{64}},
- std::pair{rcc::FloatSemantics::IEEEQuad, std::uint32_t{128}},
- std::pair{rcc::FloatSemantics::PPCDoubleDouble, std::uint32_t{128}},
- std::pair{rcc::FloatSemantics::Float8E5M2, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E5M2FNUZ, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E4M3, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E4M3FN, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E4M3FNUZ, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E4M3B11FNUZ, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float8E3M4, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::FloatTF32, std::uint32_t{19}},
- std::pair{rcc::FloatSemantics::Float8E8M0FNU, std::uint32_t{8}},
- std::pair{rcc::FloatSemantics::Float6E3M2FN, std::uint32_t{6}},
- std::pair{rcc::FloatSemantics::Float6E2M3FN, std::uint32_t{6}},
- std::pair{rcc::FloatSemantics::Float4E2M1FN, std::uint32_t{4}},
- std::pair{rcc::FloatSemantics::X87DoubleExtended, std::uint32_t{80}},
- };
-
- std::unordered_set<rcc::LLT> FloatTypes;
- for (const auto &[Semantics, BitWidth] : FloatCases) {
- auto Type = rcc::LLT::makeFloat(Semantics);
- Context.expect(Type.has_value(), "known floating-point semantics must be accepted");
- if (!Type)
- continue;
- Context.expect(Type->scalarBitWidth() == BitWidth,
- "float LLT must preserve its semantics bit width");
- Context.expect(Type->floatSemantics() == Semantics,
- "float LLT must preserve exact floating-point semantics");
- FloatTypes.insert(*Type);
- }
- Context.expect(FloatTypes.size() == FloatCases.size(),
- "distinct floating-point semantics must produce distinct LLTs");
- Context.expect(!rcc::LLT::makeFloat(rcc::FloatSemantics::Count),
- "unknown floating-point semantics must be rejected");
+ Context.expect(!rcc::LowLevelType::makeCategoryNeutralScalar(0),
+ "zero-width scalar LowLevelType must be rejected");
+ Context.expect(!rcc::LowLevelType::makeCategoryNeutralScalar(std::uint64_t{1} << 16),
+ "scalar LowLevelType wider than the encoding must be rejected");
- auto Pointer = rcc::LLT::makePointer(rcc::LLT::MaxAddressSpace, 64);
+ auto Pointer = rcc::LowLevelType::makePointer(rcc::LowLevelType::MaxAddressSpace, 64);
Context.expect(Pointer.has_value(), "maximum encodable pointer address space must be accepted");
if (Pointer) {
- Context.expect(Pointer->isPointer(), "pointer LLT must preserve its kind");
- Context.expect(Pointer->addressSpace() == rcc::LLT::MaxAddressSpace,
- "pointer LLT must preserve its address space");
+ Context.expect(Pointer->isPointer(), "pointer LowLevelType must preserve its kind");
+ Context.expect(Pointer->addressSpace() == rcc::LowLevelType::MaxAddressSpace,
+ "pointer LowLevelType must preserve its address space");
Context.expect(Pointer->toString() == "p16777215:64",
- "pointer LLT spelling must preserve address space and width");
+ "pointer LowLevelType spelling must preserve address space and width");
}
- Context.expect(!rcc::LLT::makePointer(std::uint64_t{1} << 24, 64),
+ Context.expect(!rcc::LowLevelType::makePointer(std::uint64_t{1} << 24, 64),
"pointer address spaces wider than the encoding must be rejected");
- auto I33 = rcc::LLT::makeInteger(33);
+ auto I33 = rcc::LowLevelType::makeCategoryNeutralScalar(33);
if (!I33) {
Context.expect(false, "i33 construction must succeed before vector tests");
return;
}
- auto FixedVector = rcc::LLT::makeFixedVector(4, *I33);
- Context.expect(FixedVector.has_value(), "fixed integer vector LLT must be accepted");
+ auto FixedVector = rcc::LowLevelType::makeFixedVector(4, *I33);
+ Context.expect(FixedVector.has_value(), "fixed integer vector LowLevelType must be accepted");
if (FixedVector) {
- Context.expect(FixedVector->isVector(), "fixed vector LLT must preserve vector kind");
+ Context.expect(FixedVector->isVector(), "fixed vector LowLevelType must preserve vector kind");
Context.expect(!FixedVector->isScalableVector(),
- "fixed vector LLT must not be marked scalable");
+ "fixed vector LowLevelType must not be marked scalable");
Context.expect(FixedVector->minimumElementCount() == 4,
- "fixed vector LLT must preserve element count");
+ "fixed vector LowLevelType must preserve element count");
Context.expect(FixedVector->scalarElementType() == I33,
- "fixed vector LLT must preserve its scalar element type");
- Context.expect(FixedVector->toString() == "<4 x i33>",
- "fixed vector LLT spelling must be stable");
+ "fixed vector LowLevelType must preserve its scalar element type");
+ Context.expect(FixedVector->toString() == "<4 x s33>",
+ "fixed vector LowLevelType spelling must be stable");
}
- auto BFloat = rcc::LLT::makeFloat(rcc::FloatSemantics::BFloat);
- if (!BFloat) {
- Context.expect(false, "bfloat construction must succeed before vector tests");
+ auto S16 = rcc::LowLevelType::makeCategoryNeutralScalar(16);
+ if (!S16) {
+ Context.expect(false, "s16 construction must succeed before vector tests");
return;
}
- auto ScalableVector = rcc::LLT::makeScalableVector(1, *BFloat);
+ auto ScalableVector = rcc::LowLevelType::makeScalableVector(1, *S16);
Context.expect(ScalableVector.has_value(), "scalable vector with one minimum lane must work");
if (ScalableVector) {
Context.expect(ScalableVector->isScalableVector(),
- "scalable vector LLT must preserve scalability");
- Context.expect(ScalableVector->isFloatVector() && !ScalableVector->isFloat(),
- "float vectors must not be classified as scalar floats");
- Context.expect(ScalableVector->floatSemantics() == rcc::FloatSemantics::BFloat,
- "float vectors must preserve exact floating-point semantics");
- Context.expect(ScalableVector->toString() == "<vscale x 1 x bf16>",
- "scalable float vector spelling must preserve exact semantics");
+ "scalable vector LowLevelType must preserve scalability");
+ Context.expect(ScalableVector->isVectorValue(),
+ "category-neutral vectors must preserve their value kind");
+ Context.expect(ScalableVector->scalarElementType() == S16,
+ "scalable vectors must preserve their element type");
+ Context.expect(ScalableVector->toString() == "<vscale x 1 x s16>",
+ "scalable vector spelling must preserve its shape");
}
- Context.expect(!rcc::LLT::makeFixedVector(1, *I33), "single-lane fixed vectors must be rejected");
- Context.expect(!rcc::LLT::makeScalableVector(0, *I33),
+ Context.expect(!rcc::LowLevelType::makeFixedVector(1, *I33),
+ "single-lane fixed vectors must be rejected");
+ Context.expect(!rcc::LowLevelType::makeScalableVector(0, *I33),
"zero-lane scalable vectors must be rejected");
- Context.expect(!rcc::LLT::makeFixedVector(4, Token), "token vector elements must be rejected");
+ Context.expect(!rcc::LowLevelType::makeFixedVector(4, Token),
+ "token vector elements must be rejected");
if (FixedVector) {
- Context.expect(!rcc::LLT::makeFixedVector(4, *FixedVector),
- "nested LLT vectors must be rejected");
+ Context.expect(!rcc::LowLevelType::makeFixedVector(4, *FixedVector),
+ "nested LowLevelType vectors must be rejected");
}
}
diff --git a/backend/unittests/CodeGen/GenericOpcodesTest.cpp b/backend/unittests/CodeGen/GenericOpcodesTest.cpp
index 73c1c36..f946c90 100644
--- a/backend/unittests/CodeGen/GenericOpcodesTest.cpp
+++ b/backend/unittests/CodeGen/GenericOpcodesTest.cpp
@@ -53,7 +53,8 @@ private:
return std::move(*Operand);
}
-[[nodiscard]] rcc::Register createVirtualRegister(rcc::MachineFunction &Function, rcc::LLT Type) {
+[[nodiscard]] rcc::Register createVirtualRegister(rcc::MachineFunction &Function,
+ rcc::LowLevelType Type) {
auto Reg = Function.registerInfo().createVirtualRegister(Type);
if (!Reg)
std::terminate();
@@ -284,16 +285,19 @@ void testShapesAndTypes(TestContext &Context) {
if (!Set || !Function)
return;
- auto I32 = rcc::LLT::makeInteger(32);
- auto I64 = rcc::LLT::makeInteger(64);
- auto I1 = rcc::LLT::makeInteger(1);
- auto S16 = rcc::LLT::makeAnyScalar(16);
- auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
- auto P64 = rcc::LLT::makePointer(0, 64);
- auto V2I32 = I32 ? rcc::LLT::makeFixedVector(2, *I32) : rcc::Expected<rcc::LLT>{};
- auto V4I32 = I32 ? rcc::LLT::makeFixedVector(4, *I32) : rcc::Expected<rcc::LLT>{};
- auto V2P64 = P64 ? rcc::LLT::makeFixedVector(2, *P64) : rcc::Expected<rcc::LLT>{};
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto S16 = rcc::LowLevelType::makeCategoryNeutralScalar(16);
+ auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto P64 = rcc::LowLevelType::makePointer(0, 64);
+ auto V2I32 =
+ I32 ? rcc::LowLevelType::makeFixedVector(2, *I32) : rcc::Expected<rcc::LowLevelType>{};
+ auto V4I32 =
+ I32 ? rcc::LowLevelType::makeFixedVector(4, *I32) : rcc::Expected<rcc::LowLevelType>{};
+ auto V2P64 =
+ P64 ? rcc::LowLevelType::makeFixedVector(2, *P64) : rcc::Expected<rcc::LowLevelType>{};
if (!I1 || !I32 || !I64 || !S16 || !F32 || !F64 || !P64 || !V2I32 || !V4I32 || !V2P64)
std::terminate();
auto Dst32 = (*Function)->registerInfo().createVirtualRegister(*I32);
@@ -324,7 +328,7 @@ void testShapesAndTypes(TestContext &Context) {
AddOperands.back() = registerOperand(*Wide, false);
Context.expect(!Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_ADD), AddOperands,
(*Function)->registerInfo()),
- "G_ADD must reject a source from a different LLT equality group");
+ "G_ADD must reject a source from a different LowLevelType equality group");
auto ZeroImmediate = rcc::APInt::fromUnsigned(64, 0);
std::vector<rcc::MachineOperand> PointerConstant;
@@ -483,10 +487,6 @@ void testShapesAndTypes(TestContext &Context) {
FloatingLoad, (*Function)->registerInfo())
.has_value(),
"G_FPEXTLOAD must accept a scalar floating result and pointer address");
- FloatingLoad[0] = registerOperand(*Wide, true);
- Context.expect(!Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_FPEXTLOAD),
- FloatingLoad, (*Function)->registerInfo()),
- "G_FPEXTLOAD must reject an integer result");
const std::array<std::uint64_t, 1> FloatWords{0};
auto FloatBits = rcc::APFloat::create(rcc::FloatSemantics::IEEESingle, FloatWords);
@@ -513,7 +513,7 @@ void testShapesAndTypes(TestContext &Context) {
Context.expect(Set->validateExplicitOperands(rcc::opcode(rcc::GenericOpcode::G_FCONSTANT),
FConstantOperands, (*Function)->registerInfo())
.has_value(),
- "G_FCONSTANT must accept a bit-width-compatible LLVM scalar LLT");
+ "G_FCONSTANT must accept a bit-width-compatible LLVM scalar LowLevelType");
}
void testInstructionMemorySemantics(TestContext &Context) {
@@ -524,12 +524,12 @@ void testInstructionMemorySemantics(TestContext &Context) {
if (!Set || !Function)
return;
- const rcc::LLT I1 = *rcc::LLT::makeInteger(1);
- const rcc::LLT I32 = *rcc::LLT::makeInteger(32);
- const rcc::LLT I64 = *rcc::LLT::makeInteger(64);
- const rcc::LLT F64 = *rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
- const rcc::LLT P0 = *rcc::LLT::makePointer(0, 64);
- const rcc::LLT P1 = *rcc::LLT::makePointer(1, 64);
+ const rcc::LowLevelType I1 = *rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ const rcc::LowLevelType I32 = *rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ const rcc::LowLevelType I64 = *rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ const rcc::LowLevelType F64 = *rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ const rcc::LowLevelType P0 = *rcc::LowLevelType::makePointer(0, 64);
+ const rcc::LowLevelType P1 = *rcc::LowLevelType::makePointer(1, 64);
const rcc::Register Dst32 = createVirtualRegister(**Function, I32);
const rcc::Register Dst64 = createVirtualRegister(**Function, I64);
const rcc::Register Src32 = createVirtualRegister(**Function, I32);
@@ -555,7 +555,7 @@ void testInstructionMemorySemantics(TestContext &Context) {
createInstruction(**Function, rcc::GenericOpcode::G_LOAD, std::move(OversizedLoadOperands));
addMemOperand(**Function, OversizedLoad, memoryDescription({rcc::MemoryAccessFlag::Load}, 8));
Context.expect(!Set->validateInstruction(OversizedLoad, (*Function)->registerInfo()),
- "G_LOAD must reject an MMO larger than its result LLT");
+ "G_LOAD must reject an MMO larger than its result LowLevelType");
std::vector<rcc::MachineOperand> WrongAddressSpaceOperands;
WrongAddressSpaceOperands.push_back(registerOperand(Dst64, true));
@@ -648,18 +648,6 @@ void testInstructionMemorySemantics(TestContext &Context) {
Context.expect(Set->validateInstruction(FloatingAtomic, (*Function)->registerInfo()).has_value(),
"floating atomic RMW must accept a scalar floating value and RMW MMO");
- std::vector<rcc::MachineOperand> WrongFloatingAtomicOperands;
- WrongFloatingAtomicOperands.push_back(registerOperand(Dst64, true));
- WrongFloatingAtomicOperands.push_back(registerOperand(Address0, false));
- WrongFloatingAtomicOperands.push_back(registerOperand(Src64, false));
- rcc::MachineInstr &WrongFloatingAtomic = createInstruction(
- **Function, rcc::GenericOpcode::G_ATOMICRMW_FADD, std::move(WrongFloatingAtomicOperands));
- addMemOperand(**Function, WrongFloatingAtomic,
- memoryDescription({rcc::MemoryAccessFlag::Load, rcc::MemoryAccessFlag::Store}, 8, 0,
- rcc::AtomicOperation::ReadModifyWrite));
- Context.expect(!Set->validateInstruction(WrongFloatingAtomic, (*Function)->registerInfo()),
- "floating atomic RMW must reject integer value registers");
-
std::vector<rcc::MachineOperand> PrefetchOperands;
PrefetchOperands.push_back(registerOperand(Address0, false));
PrefetchOperands.push_back(rcc::MachineOperand::immediate(0));
diff --git a/backend/unittests/CodeGen/GlobalISel/GISelMITest.h b/backend/unittests/CodeGen/GlobalISel/GISelMITest.h
index 5b16535..20e8854 100644
--- a/backend/unittests/CodeGen/GlobalISel/GISelMITest.h
+++ b/backend/unittests/CodeGen/GlobalISel/GISelMITest.h
@@ -58,8 +58,8 @@ struct FunctionFixture final {
[[nodiscard]] inline rcc::Register
createRegister(TestContext &Context, rcc::MachineFunction &Function, std::uint32_t Bits) {
- auto Type = rcc::LLT::makeInteger(Bits);
- Context.expect(Type.has_value(), "integer LLT construction must succeed");
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
+ Context.expect(Type.has_value(), "integer LowLevelType construction must succeed");
if (!Type)
return {};
auto Reg = Function.registerInfo().createVirtualRegister(*Type);
@@ -69,8 +69,8 @@ createRegister(TestContext &Context, rcc::MachineFunction &Function, std::uint32
[[nodiscard]] inline rcc::Register createFloatRegister(TestContext &Context,
rcc::MachineFunction &Function) {
- auto Type = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
- Context.expect(Type.has_value(), "floating LLT construction must succeed");
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ Context.expect(Type.has_value(), "floating LowLevelType construction must succeed");
if (!Type)
return {};
auto Reg = Function.registerInfo().createVirtualRegister(*Type);
diff --git a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
index 30c2b89..6d9fa3c 100644
--- a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
@@ -252,9 +252,9 @@ void testExtendedRV64GCPipeline(TestContext &Context) {
"extended pipeline fixture must be complete");
if (!Target || !Fixture.Function || Fixture.Entry == nullptr)
return;
- auto I1 = rcc::LLT::makeInteger(1);
- auto I64 = rcc::LLT::makeInteger(64);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
if (!I1 || !I64 || !Pointer)
return;
const rcc::Register Left = createRegister(Context, *Fixture.Function, 64);
diff --git a/backend/unittests/CodeGen/InstructionDescriptorTest.cpp b/backend/unittests/CodeGen/InstructionDescriptorTest.cpp
index 687e723..d263725 100644
--- a/backend/unittests/CodeGen/InstructionDescriptorTest.cpp
+++ b/backend/unittests/CodeGen/InstructionDescriptorTest.cpp
@@ -197,7 +197,7 @@ void testOperandValidation(TestContext &Context) {
if (!Function)
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = (*Function)->registerInfo().createVirtualRegister(*I64);
auto Source = (*Function)->registerInfo().createVirtualRegister(*I64);
Context.expect(Destination && Source, "descriptor test virtual registers must be allocated");
@@ -261,7 +261,7 @@ void testInstructionValidation(TestContext &Context) {
if (!InstructionSet || !Function)
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = (*Function)->registerInfo().createVirtualRegister(*I64);
Context.expect(Reg.has_value(), "instruction validation register must be allocated");
if (!Reg)
diff --git a/backend/unittests/CodeGen/LiveTestSupport.h b/backend/unittests/CodeGen/LiveTestSupport.h
index 071e572..f6a3566 100644
--- a/backend/unittests/CodeGen/LiveTestSupport.h
+++ b/backend/unittests/CodeGen/LiveTestSupport.h
@@ -152,7 +152,7 @@ createFunction(std::string Name, std::uint64_t ID, std::size_t BlockCount) {
}
[[nodiscard]] inline rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function) {
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Reg = Function.registerInfo().createVirtualRegister(*Type);
diff --git a/backend/unittests/CodeGen/MachineAnalysesTest.cpp b/backend/unittests/CodeGen/MachineAnalysesTest.cpp
index 997d031..53cd847 100644
--- a/backend/unittests/CodeGen/MachineAnalysesTest.cpp
+++ b/backend/unittests/CodeGen/MachineAnalysesTest.cpp
@@ -228,8 +228,8 @@ void testMemoryDependence(TestContext &Context, const rcc::TargetDescription &Ta
}
auto Block = appendBlock(**Function);
auto OtherBlock = appendBlock(**Function);
- auto I64 = rcc::LLT::makeInteger(64);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
auto Value = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64)
: rcc::Expected<rcc::Register>{std::unexpected(I64.error())};
auto Address = Pointer ? (*Function)->registerInfo().createVirtualRegister(*Pointer)
@@ -397,7 +397,7 @@ void testCFGUpdaterPHIs(TestContext &Context, const rcc::TargetDescription &Targ
return;
}
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64)
: rcc::Expected<rcc::Register>{std::unexpected(I64.error())};
auto SourceValue = I64 ? (*Function)->registerInfo().createVirtualRegister(*I64)
@@ -475,7 +475,7 @@ void testCFGUpdaterFailureAtomicity(TestContext &Context, const rcc::TargetDescr
if (!SplitUpdater.addSuccessor(**Source, **Merge, rcc::BranchProbability::one()))
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = I64 ? (*SplitFunction)->registerInfo().createVirtualRegister(*I64)
: rcc::Expected<rcc::Register>{std::unexpected(I64.error())};
auto Value = I64 ? (*SplitFunction)->registerInfo().createVirtualRegister(*I64)
diff --git a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp
index e5acc04..82bcce1 100644
--- a/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp
+++ b/backend/unittests/CodeGen/MachineFunctionClonerTest.cpp
@@ -305,7 +305,7 @@ struct SourceFixture final {
auto HistoricalInstruction = Function.createInstruction(rcc::Opcode::fromValue(NopOpcode));
Context.expect(HistoricalBlock && HistoricalInstruction, "source arena history must be created");
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Tombstone = Function.registerInfo().createVirtualRegister(*Type);
Context.expect(Tombstone && Function.registerInfo().eraseVirtualRegister(*Tombstone).has_value(),
"source vreg history must contain a tombstone");
diff --git a/backend/unittests/CodeGen/MachineIRBuilderTest.cpp b/backend/unittests/CodeGen/MachineIRBuilderTest.cpp
index 44a0e32..17e9874 100644
--- a/backend/unittests/CodeGen/MachineIRBuilderTest.cpp
+++ b/backend/unittests/CodeGen/MachineIRBuilderTest.cpp
@@ -186,7 +186,7 @@ void testTransactionalBuild(TestContext &Context) {
if (Block == nullptr)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = Function->registerInfo().createVirtualRegister(*Type);
auto Source = Function->registerInfo().createVirtualRegister(*Type);
Context.expect(Destination && Source, "builder virtual registers must be allocated");
@@ -331,7 +331,7 @@ void testImplicitAndMemoryValidation(TestContext &Context) {
if (Block == nullptr || OtherBlock == nullptr)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = Function->registerInfo().createVirtualRegister(*Type);
auto Source = Function->registerInfo().createVirtualRegister(*Type);
Context.expect(Destination && Source, "implicit test virtual registers must be allocated");
@@ -497,7 +497,7 @@ void testStaleCursorsAndOwnedOperands(TestContext &Context) {
if (Block == nullptr)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = Function->registerInfo().createVirtualRegister(*Type);
auto Source = Function->registerInfo().createVirtualRegister(*Type);
if (!Destination || !Source)
diff --git a/backend/unittests/CodeGen/MachineIRCoreTest.cpp b/backend/unittests/CodeGen/MachineIRCoreTest.cpp
index 6365e59..875eeb8 100644
--- a/backend/unittests/CodeGen/MachineIRCoreTest.cpp
+++ b/backend/unittests/CodeGen/MachineIRCoreTest.cpp
@@ -116,7 +116,8 @@ void testOperandKinds(TestContext &Context) {
Context.expect(!rcc::APFloat::create(rcc::FloatSemantics::IEEEHalf, TooManyHalfWords),
"floating immediate word-count mismatch must be rejected");
- auto Virtual = Function->registerInfo().createVirtualRegister(*rcc::LLT::makeInteger(32));
+ auto Virtual = Function->registerInfo().createVirtualRegister(
+ *rcc::LowLevelType::makeCategoryNeutralScalar(32));
Context.expect(Virtual.has_value(), "operand test virtual register must be created");
if (!Virtual)
return;
@@ -205,7 +206,7 @@ void testRegisterInfoAndOperandMovement(TestContext &Context) {
if (Block == nullptr)
return;
- auto I32 = rcc::LLT::makeInteger(32);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
Context.expect(I32.has_value(), "i32 construction for MRI test must succeed");
if (!I32)
return;
@@ -317,7 +318,7 @@ void testRegisterInfoAndOperandMovement(TestContext &Context) {
Context.expect(V0Info && V0Info->get().Type == I32 &&
V0Info->get().Bank == rcc::RegisterBankID::fromValue(3) &&
V0Info->get().RegClass == rcc::RegisterClassID::fromValue(4),
- "MRI virtual register properties must evolve without losing LLT");
+ "MRI virtual register properties must evolve without losing LowLevelType");
Context.expect(MRI.addLiveIn(*PhysReg, *V0).has_value(),
"MRI must record function physical live-ins");
diff --git a/backend/unittests/CodeGen/MachineOptimizationTest.cpp b/backend/unittests/CodeGen/MachineOptimizationTest.cpp
index bb2c0e1..cffd4e1 100644
--- a/backend/unittests/CodeGen/MachineOptimizationTest.cpp
+++ b/backend/unittests/CodeGen/MachineOptimizationTest.cpp
@@ -169,10 +169,10 @@ void setPostRAProperties(rcc::MachineFunction &Function) {
}
[[nodiscard]] rcc::Register makeGPR(TestContext &Context, rcc::MachineFunction &Function) {
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Type ? Function.registerInfo().createVirtualRegister(*Type)
- : rcc::Expected<rcc::Register>(std::unexpected(
- rcc::Error(rcc::ErrorCode::InternalError, "test LLT creation failed")));
+ : rcc::Expected<rcc::Register>(std::unexpected(rcc::Error(
+ rcc::ErrorCode::InternalError, "test LowLevelType creation failed")));
Context.expect(Reg.has_value(), "optimization virtual register creation must succeed");
if (!Reg)
return {};
diff --git a/backend/unittests/CodeGen/MachineSchedulingTest.cpp b/backend/unittests/CodeGen/MachineSchedulingTest.cpp
index 5162fb8..a3d1de9 100644
--- a/backend/unittests/CodeGen/MachineSchedulingTest.cpp
+++ b/backend/unittests/CodeGen/MachineSchedulingTest.cpp
@@ -178,10 +178,10 @@ makeSchedulingModel(const rcc::TargetSchedulingHooks *Hooks = nullptr) {
}
[[nodiscard]] rcc::Register makeGPR(TestContext &Context, rcc::MachineFunction &Function) {
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Type ? Function.registerInfo().createVirtualRegister(*Type)
- : rcc::Expected<rcc::Register>(std::unexpected(
- rcc::Error(rcc::ErrorCode::InternalError, "test LLT creation failed")));
+ : rcc::Expected<rcc::Register>(std::unexpected(rcc::Error(
+ rcc::ErrorCode::InternalError, "test LowLevelType creation failed")));
Context.expect(Reg.has_value(), "scheduler virtual register creation must succeed");
if (!Reg)
return {};
diff --git a/backend/unittests/CodeGen/MachineValueTypesTest.cpp b/backend/unittests/CodeGen/MachineValueTypesTest.cpp
index 819d6cb..315d56e 100644
--- a/backend/unittests/CodeGen/MachineValueTypesTest.cpp
+++ b/backend/unittests/CodeGen/MachineValueTypesTest.cpp
@@ -184,9 +184,9 @@ void testMachineMemOperand(TestContext &Context) {
"failure ordering stronger than success must be rejected");
auto BadAddressSpace = makeBasicLoadDescription();
- BadAddressSpace.AddressSpace = rcc::LLT::MaxAddressSpace + 1;
+ BadAddressSpace.AddressSpace = rcc::LowLevelType::MaxAddressSpace + 1;
Context.expect(!rcc::MachineMemOperand::create(BadAddressSpace),
- "MMO address space wider than LLT encoding must be rejected");
+ "MMO address space wider than LowLevelType encoding must be rejected");
auto EmptySymbol = makeBasicLoadDescription();
EmptySymbol.Base = rcc::MemoryBase::externalSymbol("");
diff --git a/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp b/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp
index 3eb926d..3cc2b56 100644
--- a/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp
+++ b/backend/unittests/CodeGen/MachineVerifierTargetTest.cpp
@@ -186,7 +186,7 @@ void testValidTargetFacts(TestContext &Context, const rcc::TargetDescription &Ta
if (!Fixture.Function)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
if (!Reg)
return;
@@ -233,7 +233,7 @@ void testSubRegisterProjection(TestContext &Context, const rcc::TargetDescriptio
if (!Fixture.Function)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
if (!Reg)
return;
@@ -282,7 +282,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context,
}
{
auto Fixture = createFunction(Context, "unknown_bank", 5);
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Fixture.Function || !Type)
return;
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
@@ -295,7 +295,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context,
}
{
auto Fixture = createFunction(Context, "wide_bank_value", 6);
- auto Type = rcc::LLT::makeInteger(128);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(128);
if (!Fixture.Function || !Type)
return;
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
@@ -325,7 +325,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context,
}
{
auto Fixture = createFunction(Context, "bad_allocation_hint", 9);
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
Context.expect(Reg &&
classify(Fixture.Function->registerInfo(), *Reg,
@@ -340,7 +340,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context,
}
{
auto Fixture = createFunction(Context, "reserved_allocation_hint", 14);
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
const auto G0 = phys(rcc::test::TestRegister::G0);
Context.expect(Reg &&
@@ -355,7 +355,7 @@ void testUnknownAndMalformedTargetFacts(TestContext &Context,
}
{
auto Fixture = createFunction(Context, "incompatible_function_livein", 15);
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Reg = Fixture.Function->registerInfo().createVirtualRegister(*Type);
Context.expect(
Reg &&
@@ -416,7 +416,7 @@ void testRegMaskEarlyClobberAndTies(TestContext &Context, const rcc::TargetDescr
}
{
auto Fixture = createFunction(Context, "incompatible_tie", 12);
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto GPR = Fixture.Function->registerInfo().createVirtualRegister(*Type);
auto FPR = Fixture.Function->registerInfo().createVirtualRegister(*Type);
if (!GPR || !FPR)
diff --git a/backend/unittests/CodeGen/MachineVerifierTest.cpp b/backend/unittests/CodeGen/MachineVerifierTest.cpp
index c8c512f..5327148 100644
--- a/backend/unittests/CodeGen/MachineVerifierTest.cpp
+++ b/backend/unittests/CodeGen/MachineVerifierTest.cpp
@@ -196,7 +196,7 @@ buildNoOperand(TestContext &Context, rcc::MachineIRBuilder &Builder, std::uint32
if (Entry == nullptr || Exit == nullptr)
return false;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Value = Function.registerInfo().createVirtualRegister(*Type);
Context.expect(Value.has_value(), "typed verifier virtual register must be allocated");
if (!Value)
@@ -338,7 +338,7 @@ createPhiTestFunction(TestContext &Context, const rcc::TargetDescription &Target
return nullptr;
}
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Destination = Type ? Function->registerInfo().createVirtualRegister(*Type)
: rcc::Expected<rcc::Register>{std::unexpected(Type.error())};
auto LeftValue = Type ? Function->registerInfo().createVirtualRegister(*Type)
@@ -411,7 +411,7 @@ void testPropertyFailures(TestContext &Context) {
auto Target = createTarget();
if (!Target)
return;
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto SSA = createFunction(Context, "ssa", 6);
rcc::MachineBasicBlock *SSABlock = SSA ? createBlock(Context, *SSA) : nullptr;
@@ -503,7 +503,7 @@ void testPropertyFailures(TestContext &Context) {
void testSelectedStateAndPseudoDeadline(TestContext &Context) {
auto Target = createTarget();
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Target)
return;
diff --git a/backend/unittests/CodeGen/PHIEliminationTest.cpp b/backend/unittests/CodeGen/PHIEliminationTest.cpp
index 9bc9a57..bbc834f 100644
--- a/backend/unittests/CodeGen/PHIEliminationTest.cpp
+++ b/backend/unittests/CodeGen/PHIEliminationTest.cpp
@@ -90,7 +90,7 @@ void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescrip
auto Fixture = createFunction(Context, "parallel_phis", 1, 3);
if (!Fixture.Function || Fixture.Blocks.size() != 3)
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return;
auto &Function = *Fixture.Function;
@@ -209,7 +209,7 @@ void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescrip
Context.expect(FreshInfo.has_value(), "fresh PHI vreg must remain registered");
if (!FreshInfo)
return;
- Context.expect(FreshInfo->get().Type == I64, "fresh PHI vreg must clone its LLT");
+ Context.expect(FreshInfo->get().Type == I64, "fresh PHI vreg must clone its LowLevelType");
Context.expect(FreshInfo->get().Bank == rcc::test::TestRegisterBank::GPR,
"fresh PHI vreg must clone its register bank");
Context.expect(FreshInfo->get().RegClass == rcc::test::TestRegisterClass::GPR64,
@@ -241,7 +241,7 @@ void testCriticalEdgeAndPhysicalLiveIn(TestContext &Context, const rcc::TargetDe
auto Fixture = createFunction(Context, "critical_edge", 2, 4);
if (!Fixture.Function || Fixture.Blocks.size() != 4)
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return;
auto &Function = *Fixture.Function;
@@ -343,7 +343,7 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip
auto Fixture = createFunction(Context, "undef_phi", ID, 2);
if (!Fixture.Function || Fixture.Blocks.size() != 2)
return Fixture;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!I64)
return Fixture;
auto Source = createVReg(*Fixture.Function, *I64, rcc::test::TestRegisterBank::GPR,
@@ -406,9 +406,9 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip
}
void testMalformedPHIs(TestContext &Context, const rcc::TargetDescription &Target) {
- auto BuildBadPhi = [&](std::uint64_t ID, rcc::LLT DestinationType,
+ auto BuildBadPhi = [&](std::uint64_t ID, rcc::LowLevelType DestinationType,
rcc::RegisterBankID DestinationBank, rcc::RegisterClassID DestinationClass,
- rcc::LLT SourceType, rcc::RegisterBankID SourceBank,
+ rcc::LowLevelType SourceType, rcc::RegisterBankID SourceBank,
rcc::RegisterClassID SourceClass, rcc::SubRegIndex SourceSubReg = {}) {
auto Fixture = createFunction(Context, "bad_phi", ID, 2);
if (!Fixture.Function || Fixture.Blocks.size() != 2)
@@ -438,8 +438,8 @@ void testMalformedPHIs(TestContext &Context, const rcc::TargetDescription &Targe
return Fixture;
};
- auto I64 = rcc::LLT::makeInteger(64);
- auto I32 = rcc::LLT::makeInteger(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
if (!I64 || !I32)
return;
auto BadType =
diff --git a/backend/unittests/CodeGen/RegisterAllocationTest.cpp b/backend/unittests/CodeGen/RegisterAllocationTest.cpp
index 7dd0dd0..443d00a 100644
--- a/backend/unittests/CodeGen/RegisterAllocationTest.cpp
+++ b/backend/unittests/CodeGen/RegisterAllocationTest.cpp
@@ -352,7 +352,7 @@ struct FunctionFixture final {
[[nodiscard]] rcc::Expected<rcc::Register>
createVReg(rcc::MachineFunction &Function,
rcc::RegisterClassID Class = rcc::test::TestRegisterClass::GPR64) {
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Reg = Function.registerInfo().createVirtualRegister(*Type);
diff --git a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
index d93b14e..7f0a641 100644
--- a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
+++ b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
@@ -201,7 +201,7 @@ struct FunctionFixture final {
[[nodiscard]] inline Expected<Register>
createVReg(MachineFunction &Function, RegisterClassID Class = TestRegisterClass::GPR64) {
- auto Type = LLT::makeInteger(64);
+ auto Type = LowLevelType::makeCategoryNeutralScalar(64);
if (!Type)
return std::unexpected(Type.error());
auto Reg = Function.registerInfo().createVirtualRegister(*Type);
diff --git a/backend/unittests/CodeGen/SSAExitTestSupport.h b/backend/unittests/CodeGen/SSAExitTestSupport.h
index 5729293..cf77d36 100644
--- a/backend/unittests/CodeGen/SSAExitTestSupport.h
+++ b/backend/unittests/CodeGen/SSAExitTestSupport.h
@@ -360,7 +360,7 @@ struct FunctionFixture final {
}
[[nodiscard]] inline rcc::Expected<rcc::Register>
-createVReg(rcc::MachineFunction &Function, rcc::LLT Type, rcc::RegisterBankID Bank,
+createVReg(rcc::MachineFunction &Function, rcc::LowLevelType Type, rcc::RegisterBankID Bank,
rcc::RegisterClassID Class, std::uint8_t TargetFlags = 0,
std::optional<rcc::PhysicalRegister> Hint = std::nullopt) {
auto Reg = Function.registerInfo().createVirtualRegister(Type);
diff --git a/backend/unittests/CodeGen/TargetCallLoweringTest.cpp b/backend/unittests/CodeGen/TargetCallLoweringTest.cpp
index c5170d0..22a2b0c 100644
--- a/backend/unittests/CodeGen/TargetCallLoweringTest.cpp
+++ b/backend/unittests/CodeGen/TargetCallLoweringTest.cpp
@@ -42,8 +42,8 @@ private:
return *Value;
}
-[[nodiscard]] rcc::LLT integer(std::uint32_t Bits) {
- const auto Type = rcc::LLT::makeInteger(Bits);
+[[nodiscard]] rcc::LowLevelType integer(std::uint32_t Bits) {
+ const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
if (!Type)
std::terminate();
return *Type;
@@ -207,7 +207,7 @@ void testPlanValidation(TestContext &Context) {
auto BadByVal = emptyPlanDescription(rcc::CallLoweringPlanKind::Call);
auto ByValAssignment = registerAssignment();
- ByValAssignment.ValueType = *rcc::LLT::makePointer(0, 64);
+ ByValAssignment.ValueType = *rcc::LowLevelType::makePointer(0, 64);
ByValAssignment.LocationType = ByValAssignment.ValueType;
ByValAssignment.CustomFlags.set(rcc::CCAssignmentFlag::ByVal);
BadByVal.ArgumentAssignments.push_back(ByValAssignment);
@@ -219,7 +219,7 @@ void testPlanValidation(TestContext &Context) {
auto OverlappingByVal = emptyPlanDescription(rcc::CallLoweringPlanKind::Call);
OverlappingByVal.CallFrame.SizeBytes = 32;
auto FirstByVal = registerAssignment();
- FirstByVal.ValueType = *rcc::LLT::makePointer(0, 64);
+ FirstByVal.ValueType = *rcc::LowLevelType::makePointer(0, 64);
FirstByVal.LocationType = FirstByVal.ValueType;
FirstByVal.CustomFlags.set(rcc::CCAssignmentFlag::ByVal);
auto SecondByVal = FirstByVal;
diff --git a/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp b/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp
index 2c44237..bb9a0fc 100644
--- a/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp
+++ b/backend/unittests/CodeGen/TargetRegisterInfoTest.cpp
@@ -250,7 +250,7 @@ void testTargetDescriptionConstraints(TestContext &Context) {
rcc::test::TestRegisterBank::GPR));
auto Function =
rcc::MachineFunction::create("constraints", rcc::MachineFunctionStableID::fromValue(1));
- auto Type = rcc::LLT::makeInteger(64);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!SubclassTarget || !Function || !Type)
return;
@@ -301,7 +301,7 @@ void testTargetDescriptionConstraints(TestContext &Context) {
(*Function)->registerInfo()),
"physical register operands must reject nonzero subregister indices");
- auto WideType = rcc::LLT::makeInteger(128);
+ auto WideType = rcc::LowLevelType::makeCategoryNeutralScalar(128);
if (!WideType)
return;
auto WideReg = (*Function)->registerInfo().createVirtualRegister(*WideType);
diff --git a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
index e3ad4eb..d23a2eb 100644
--- a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
+++ b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
@@ -19,8 +19,8 @@ void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::Target
auto Fixture = createFunction(Context, "two_address", 5, 1);
if (!Fixture.Function || Fixture.Blocks.empty())
return;
- auto I64 = rcc::LLT::makeInteger(64);
- auto I32 = rcc::LLT::makeInteger(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
if (!I64 || !I32)
return;
auto &Function = *Fixture.Function;
diff --git a/backend/unittests/MIR/MIParserTest.cpp b/backend/unittests/MIR/MIParserTest.cpp
index c35dc74..4ed39ae 100644
--- a/backend/unittests/MIR/MIParserTest.cpp
+++ b/backend/unittests/MIR/MIParserTest.cpp
@@ -265,8 +265,8 @@ bb.1."exit block" (landing-pad, bbsections Cold):
Context.expect(Registers.size() == 5 &&
Registers[0].RegClass == rcc::test::TestRegisterClass::GPR64 &&
Registers[1].RegClass == rcc::test::TestRegisterClass::GPR64 &&
- Registers[2].Type == *rcc::LLT::makeAnyScalar(128) &&
- Registers[3].Type == *rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble) &&
+ Registers[2].Type == *rcc::LowLevelType::makeCategoryNeutralScalar(128) &&
+ Registers[3].Type == *rcc::LowLevelType::makeCategoryNeutralScalar(64) &&
Registers[4].RegClass == rcc::test::TestRegisterClass::GPR64,
"textual virtual registers must map deterministically to classed MachineIR vregs");
@@ -385,7 +385,7 @@ void testAddressSpacePointerWidthResolver(TestContext &Context) {
"bb.0:\n %0:_(p1) = TEST_COPY $g0\n", ParserContext, ParserOptions);
auto Parsed = Parser.parse();
const auto Registers = Function->registerInfo().virtualRegisters();
- auto ExpectedType = rcc::LLT::makePointer(1, 32);
+ auto ExpectedType = rcc::LowLevelType::makePointer(1, 32);
Context.expect(Parsed.has_value() && ExpectedType.has_value() && Registers.size() == 1 &&
Registers.front().Type == *ExpectedType,
"MI parser must use the address-space-specific pointer-width resolver");
@@ -396,35 +396,6 @@ void testAddressSpacePointerWidthResolver(TestContext &Context) {
}
}
-void testUnserializableLowLevelType(TestContext &Context) {
- auto Target = createTarget();
- auto Function = createFunction(Context, 4);
- Context.expect(Target.has_value(), "unserializable-type target must be valid");
- if (!Target || !Function)
- return;
-
- rcc::mir::MIParserOptions ParserOptions;
- ParserOptions.VerifyAfterParse = false;
- rcc::mir::MIParser Parser(*Function, *Target, "unserializable-type.mir",
- "bb.0:\n %0:gpr64(f64) = TEST_COPY $g0\n", {}, ParserOptions);
- auto Parsed = Parser.parse();
- auto Register = rcc::Register::makeVirtual(0);
- auto UnsupportedType = rcc::LLT::makeFloat(rcc::FloatSemantics::Float8E5M2);
- Context.expect(Parsed.has_value() && Register.has_value() && UnsupportedType.has_value(),
- "unserializable-type test setup must parse a typed virtual register");
- if (!Parsed || !Register || !UnsupportedType)
- return;
- auto SetType = Function->registerInfo().setType(*Register, *UnsupportedType);
- Context.expect(SetType.has_value(), "test setup must assign an extended floating low-level type");
- if (!SetType)
- return;
-
- auto Printed = rcc::mir::printMachineFunctionBody(*Function, *Target);
- Context.expect(!Printed && Printed.error().message().find("cannot spell this floating") !=
- std::string_view::npos,
- "printer must reject extended low-level types absent from fixed LLVM MIR grammar");
-}
-
void expectParseError(TestContext &Context, const rcc::TargetDescription &Target, std::string Body,
std::string_view Message);
@@ -525,7 +496,7 @@ void testLLVMInlineAsmAndConstantMemorySyntax(TestContext &Context) {
const auto *ExtraInfo = InlineAsm->operandAt(1)->getIf<std::int64_t>();
const rcc::MachineInstr *Load = InlineAsm->next();
const rcc::MachineMemOperandDesc &Memory = Load->memOperands().front()->description();
- const auto MemoryType = rcc::LLT::makeAnyScalar(64);
+ const auto MemoryType = rcc::LowLevelType::makeCategoryNeutralScalar(64);
Context.expect(ExtraInfo != nullptr && *ExtraInfo == 13,
"inline-asm extra-info names must aggregate into the LLVM bit field");
Context.expect(Memory.Base.kind() == rcc::MemoryBase::Kind::IRConstant &&
@@ -629,7 +600,6 @@ int main() {
TestContext Context;
testTwoPassBodyParsing(Context);
testAddressSpacePointerWidthResolver(Context);
- testUnserializableLowLevelType(Context);
testCompatibleRegisterClassAndBankAnnotations(Context);
testTypedIntegerTruncation(Context);
testLLVMInlineAsmAndConstantMemorySyntax(Context);
diff --git a/backend/unittests/MIR/MIRDocumentTest.cpp b/backend/unittests/MIR/MIRDocumentTest.cpp
index 7f1dfc3..6d84580 100644
--- a/backend/unittests/MIR/MIRDocumentTest.cpp
+++ b/backend/unittests/MIR/MIRDocumentTest.cpp
@@ -558,7 +558,7 @@ void testHeterogeneousPointerLayout(TestContext &Context) {
}
const rcc::MachineFunction *Function = Parsed.document()->unit().function("pointer_layout");
- auto PointerType = rcc::LLT::makePointer(1, 32);
+ auto PointerType = rcc::LowLevelType::makePointer(1, 32);
const rcc::MachineConstantPoolEntry *Constant =
Function == nullptr ? nullptr
: Function->constantPool().entry(rcc::ConstantPoolIndex::fromValue(0));
@@ -584,7 +584,7 @@ void testHeterogeneousPointerLayout(TestContext &Context) {
: OverriddenFunction->constantPool().entry(rcc::ConstantPoolIndex::fromValue(0));
const rcc::MachineConstantPoolEntryDesc *OverriddenConstantDescription =
OverriddenConstant == nullptr ? nullptr : OverriddenConstant->description();
- const auto OverriddenPointerType = rcc::LLT::makePointer(1, 64);
+ const auto OverriddenPointerType = rcc::LowLevelType::makePointer(1, 64);
Context.expect(Overridden.succeeded() && OverriddenFunction != nullptr &&
OverriddenPointerType.has_value() &&
OverriddenFunction->registerInfo().virtualRegisters().size() == 1 &&
diff --git a/backend/unittests/Target/RISCVCallLoweringTest.cpp b/backend/unittests/Target/RISCVCallLoweringTest.cpp
index eee10ab..738aeb1 100644
--- a/backend/unittests/Target/RISCVCallLoweringTest.cpp
+++ b/backend/unittests/Target/RISCVCallLoweringTest.cpp
@@ -61,29 +61,30 @@ private:
return *Value;
}
-[[nodiscard]] rcc::LLT integer(std::uint32_t Bits) {
- const auto Type = rcc::LLT::makeInteger(Bits);
+[[nodiscard]] rcc::LowLevelType integer(std::uint32_t Bits) {
+ const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
if (!Type)
std::terminate();
return *Type;
}
-[[nodiscard]] rcc::LLT anyScalar(std::uint32_t Bits) {
- const auto Type = rcc::LLT::makeAnyScalar(Bits);
+[[nodiscard]] rcc::LowLevelType anyScalar(std::uint32_t Bits) {
+ const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
if (!Type)
std::terminate();
return *Type;
}
-[[nodiscard]] rcc::LLT floating(rcc::FloatSemantics Semantics) {
- const auto Type = rcc::LLT::makeFloat(Semantics);
+[[nodiscard]] rcc::LowLevelType floating(rcc::FloatSemantics Semantics) {
+ const std::uint32_t Bits = Semantics == rcc::FloatSemantics::IEEESingle ? 32 : 64;
+ const auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
if (!Type)
std::terminate();
return *Type;
}
-[[nodiscard]] rcc::LLT pointer() {
- const auto Type = rcc::LLT::makePointer(0, 64);
+[[nodiscard]] rcc::LowLevelType pointer() {
+ const auto Type = rcc::LowLevelType::makePointer(0, 64);
if (!Type)
std::terminate();
return *Type;
@@ -128,13 +129,16 @@ private:
return rcc::Register::fromPhysical(physical(rcc::riscv::PhysicalRegisterID::X5));
}
-[[nodiscard]] rcc::ABIValue
-abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = planningRegister(),
- rcc::ABIExtensionKind Extension = rcc::ABIExtensionKind::None) {
+[[nodiscard]] rcc::ABIValue abiValue(rcc::LowLevelType Type, std::uint32_t OriginalValue,
+ rcc::Register Value = planningRegister(),
+ rcc::ABIExtensionKind Extension = rcc::ABIExtensionKind::None,
+ std::optional<rcc::ABIValueCategory> Category = std::nullopt) {
const std::uint64_t Size = std::max<std::uint64_t>(1, (Type.scalarBitWidth() + 7U) / 8U);
return {
.Value = Value,
.Type = Type,
+ .Category = Category.value_or(Type.isPointer() ? rcc::ABIValueCategory::Pointer
+ : rcc::ABIValueCategory::Integer),
.OriginalValue = OriginalValue,
.FragmentIndex = 0,
.FragmentCount = 1,
@@ -147,6 +151,13 @@ abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = plann
};
}
+[[nodiscard]] rcc::ABIValue floatingABIValue(rcc::FloatSemantics Semantics,
+ std::uint32_t OriginalValue,
+ rcc::Register Value = planningRegister()) {
+ return abiValue(floating(Semantics), OriginalValue, Value, rcc::ABIExtensionKind::None,
+ rcc::ABIValueCategory::FloatingPoint);
+}
+
[[nodiscard]] std::vector<rcc::ABIValue> integerValues(std::size_t Count) {
std::vector<rcc::ABIValue> Values;
Values.reserve(Count);
@@ -160,7 +171,7 @@ abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = plann
Values.reserve(Count);
for (std::size_t Index = 0; Index < Count; ++Index) {
Values.push_back(
- abiValue(floating(rcc::FloatSemantics::IEEEDouble), static_cast<std::uint32_t>(Index)));
+ floatingABIValue(rcc::FloatSemantics::IEEEDouble, static_cast<std::uint32_t>(Index)));
}
return Values;
}
@@ -230,8 +241,8 @@ void testIntegerAndFloatingAssignments(TestContext &Context) {
FloatAssignments[16].StackOffsetBytes == 0,
"LP64D floating arguments must fall back from fa0-fa7 to a0-a7 and then stack");
- auto Single = callRequest({abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}, 1);
- Single.Results = {abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)};
+ auto Single = callRequest({floatingABIValue(rcc::FloatSemantics::IEEESingle, 0)}, 1);
+ Single.Results = {floatingABIValue(rcc::FloatSemantics::IEEESingle, 0)};
auto SinglePlan = CallLowering.planCall(Single);
Context.expect(SinglePlan && SinglePlan->argumentAssignments().size() == 1 &&
SinglePlan->returnAssignments().size() == 1 &&
@@ -241,7 +252,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) {
physical(rcc::riscv::PhysicalRegisterID::F10_F)),
"LP64D f32 arguments and returns must use the FPR32 physical-register view");
- auto FloatFragment = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0);
+ auto FloatFragment = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0);
FloatFragment.FragmentCount = 2;
FloatFragment.OriginalAlignment = align(16);
auto IntegerFragment = abiValue(integer(64), 0);
@@ -265,9 +276,9 @@ void testIntegerAndFloatingAssignments(TestContext &Context) {
GenericScalarPlan->returnAssignments()[0].ValueType == anyScalar(64),
"LLVM generic scalar LLTs must use integer ABI transport without type loss");
- auto LP64Float = callRequest({abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)}, 1);
+ auto LP64Float = callRequest({floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0)}, 1);
LP64Float.Convention = rcc::riscv::callingConventionID(rcc::riscv::CallingConvention::LP64);
- LP64Float.Results = {abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)};
+ LP64Float.Results = {floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0)};
auto LP64Plan = CallLowering.planCall(LP64Float);
const auto LP64Mask = rcc::riscv::createCallPreservedMask(rcc::riscv::CallingConvention::LP64);
Context.expect(
@@ -295,8 +306,8 @@ void testIntegerAndFloatingAssignments(TestContext &Context) {
}
void testVariadicAssignments(TestContext &Context) {
- auto FixedFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0);
- auto VariableFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1);
+ auto FixedFloat = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0);
+ auto VariableFloat = floatingABIValue(rcc::FloatSemantics::IEEEDouble, 1);
auto Request = callRequest({FixedFloat, VariableFloat}, 1, true);
auto Plan = CallLowering.planCall(Request);
Context.expect(
@@ -385,8 +396,7 @@ void testSpecialArgumentsAndReturns(TestContext &Context) {
rcc::ReturnLoweringRequest Return;
Return.Convention = convention();
- Return.Values = {abiValue(integer(64), 0),
- abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1)};
+ Return.Values = {abiValue(integer(64), 0), floatingABIValue(rcc::FloatSemantics::IEEEDouble, 1)};
auto ReturnPlan = CallLowering.planReturn(Return);
Context.expect(ReturnPlan && ReturnPlan->returnAssignments().size() == 2 &&
isLocation(ReturnPlan->returnAssignments()[0], returnGPR(0)) &&
@@ -455,7 +465,8 @@ void testTailCalls(TestContext &Context) {
return std::move(*Function);
}
-[[nodiscard]] rcc::Register virtualRegister(rcc::MachineFunction &Function, rcc::LLT Type) {
+[[nodiscard]] rcc::Register virtualRegister(rcc::MachineFunction &Function,
+ rcc::LowLevelType Type) {
auto Register = Function.registerInfo().createVirtualRegister(Type);
if (!Register)
std::terminate();
@@ -500,12 +511,12 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) {
if (!Target || !Function || Block == nullptr)
return;
- const rcc::LLT I64 = integer(64);
- const rcc::LLT F64 = floating(rcc::FloatSemantics::IEEEDouble);
+ const rcc::LowLevelType I64 = integer(64);
+ const rcc::LowLevelType F64 = floating(rcc::FloatSemantics::IEEEDouble);
const rcc::Register Argument = virtualRegister(*Function, I64);
const rcc::Register Result = virtualRegister(*Function, F64);
auto Request = callRequest({abiValue(I64, 0, Argument)}, 1);
- Request.Results = {abiValue(F64, 0, Result)};
+ Request.Results = {floatingABIValue(rcc::FloatSemantics::IEEEDouble, 0, Result)};
rcc::MachineIRBuilder Builder(*Function, *Target);
Context.expect(Builder.setInsertPoint(*Block).has_value(),
diff --git a/backend/unittests/Target/RISCVCodeGenTest.cpp b/backend/unittests/Target/RISCVCodeGenTest.cpp
index 1bc3361..7392f3b 100644
--- a/backend/unittests/Target/RISCVCodeGenTest.cpp
+++ b/backend/unittests/Target/RISCVCodeGenTest.cpp
@@ -66,7 +66,7 @@ struct InstructionFixture final {
auto Block = (*Function)->createBasicBlock();
if (!Block || !(*Function)->appendBlock(**Block))
return {};
- auto Type = rcc::LLT::makeInteger(Bits);
+ auto Type = rcc::LowLevelType::makeCategoryNeutralScalar(Bits);
if (!Type)
return {};
auto Left = (*Function)->registerInfo().createVirtualRegister(*Type);
@@ -87,29 +87,28 @@ struct InstructionFixture final {
}
[[nodiscard]] bool constrainRegister(rcc::MachineFunction &Function, rcc::Register Reg,
- rcc::LLT Type) {
- const auto Bank = Type.isFloat() ? rcc::RegisterBankID::fromValue(
- static_cast<std::uint32_t>(rcc::riscv::RegisterBank::FPR))
- : rcc::RegisterBankID::fromValue(
- static_cast<std::uint32_t>(rcc::riscv::RegisterBank::GPR));
- const auto Class = Type.isFloat()
- ? rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>(
- Type.scalarBitWidth() == 32 ? rcc::riscv::RegisterClass::FPR32
- : rcc::riscv::RegisterClass::FPR64))
- : rcc::RegisterClassID::fromValue(
- static_cast<std::uint32_t>(rcc::riscv::RegisterClass::GPR));
+ rcc::LowLevelType Type, bool Floating = false) {
+ const auto Bank = rcc::RegisterBankID::fromValue(static_cast<std::uint32_t>(
+ Floating ? rcc::riscv::RegisterBank::FPR : rcc::riscv::RegisterBank::GPR));
+ const auto Class = rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>(
+ Floating ? (Type.scalarBitWidth() == 32 ? rcc::riscv::RegisterClass::FPR32
+ : rcc::riscv::RegisterClass::FPR64)
+ : rcc::riscv::RegisterClass::GPR));
return Function.registerInfo().setRegisterBank(Reg, Bank).has_value() &&
Function.registerInfo().setRegisterClass(Reg, Class).has_value();
}
-[[nodiscard]] bool constrainVirtualRegisters(rcc::MachineFunction &Function) {
+[[nodiscard]] bool constrainVirtualRegisters(rcc::MachineFunction &Function,
+ bool FloatingValues = false) {
const auto Registers = Function.registerInfo().virtualRegisters();
for (std::size_t Index = 0; Index < Registers.size(); ++Index) {
const rcc::VirtualRegisterInfo &Info = Registers[Index];
if (Info.IsTombstone)
continue;
auto Reg = rcc::Register::makeVirtual(Index);
- if (!Reg || !Info.Type || !constrainRegister(Function, *Reg, *Info.Type))
+ if (!Reg || !Info.Type ||
+ !constrainRegister(Function, *Reg, *Info.Type,
+ FloatingValues && Info.Type->scalarBitWidth() != 1))
return false;
}
return true;
@@ -128,8 +127,10 @@ struct InstructionFixture final {
[[nodiscard]] std::unique_ptr<rcc::MachineFunction>
createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target,
- rcc::GenericOpcode Generic, rcc::LLT DestinationType, rcc::LLT SourceType,
- rcc::Register *DestinationOut = nullptr, rcc::Register *SourceOut = nullptr) {
+ rcc::GenericOpcode Generic, rcc::LowLevelType DestinationType,
+ rcc::LowLevelType SourceType, bool FloatingDestination = false,
+ bool FloatingSource = false, rcc::Register *DestinationOut = nullptr,
+ rcc::Register *SourceOut = nullptr) {
auto Function = rcc::MachineFunction::create(
"riscv_unary",
rcc::MachineFunctionStableID::fromValue(200 + static_cast<std::uint32_t>(Generic)));
@@ -143,8 +144,8 @@ createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target,
auto Source = (*Function)->registerInfo().createVirtualRegister(SourceType);
if (!Destination || !Source)
return nullptr;
- if (!constrainRegister(**Function, *Destination, DestinationType) ||
- !constrainRegister(**Function, *Source, SourceType))
+ if (!constrainRegister(**Function, *Destination, DestinationType, FloatingDestination) ||
+ !constrainRegister(**Function, *Source, SourceType, FloatingSource))
return nullptr;
rcc::MachineIRBuilder Builder(**Function, Target);
if (!Builder.setInsertPoint(**Block))
@@ -161,7 +162,7 @@ createUnaryFunction(TestContext &Context, const rcc::TargetDescription &Target,
[[nodiscard]] std::unique_ptr<rcc::MachineFunction>
createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target,
- rcc::GenericOpcode Generic, rcc::LLT ValueType, bool Floating,
+ rcc::GenericOpcode Generic, rcc::LowLevelType ValueType, bool Floating,
rcc::IntegerPredicate IntegerCondition,
rcc::FloatingPredicate FloatingCondition) {
auto Function = rcc::MachineFunction::create(
@@ -173,15 +174,15 @@ createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target
auto Block = (*Function)->createBasicBlock();
if (!Block || !(*Function)->appendBlock(**Block))
return nullptr;
- auto ResultType = rcc::LLT::makeInteger(1);
+ auto ResultType = rcc::LowLevelType::makeCategoryNeutralScalar(1);
if (!ResultType)
return nullptr;
auto Result = (*Function)->registerInfo().createVirtualRegister(*ResultType);
auto Left = (*Function)->registerInfo().createVirtualRegister(ValueType);
auto Right = (*Function)->registerInfo().createVirtualRegister(ValueType);
if (!Result || !Left || !Right || !constrainRegister(**Function, *Result, *ResultType) ||
- !constrainRegister(**Function, *Left, ValueType) ||
- !constrainRegister(**Function, *Right, ValueType))
+ !constrainRegister(**Function, *Left, ValueType, Floating) ||
+ !constrainRegister(**Function, *Right, ValueType, Floating))
return nullptr;
rcc::MachineIRBuilder Builder(**Function, Target);
if (!Builder.setInsertPoint(**Block))
@@ -202,7 +203,7 @@ createCompareFunction(TestContext &Context, const rcc::TargetDescription &Target
[[nodiscard]] std::unique_ptr<rcc::MachineFunction>
createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Target,
- rcc::GenericOpcode Generic, rcc::LLT Type) {
+ rcc::GenericOpcode Generic, rcc::LowLevelType Type) {
auto Function = rcc::MachineFunction::create(
"riscv_float_binary",
rcc::MachineFunctionStableID::fromValue(700 + static_cast<std::uint32_t>(Generic)));
@@ -215,8 +216,9 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta
auto Left = (*Function)->registerInfo().createVirtualRegister(Type);
auto Right = (*Function)->registerInfo().createVirtualRegister(Type);
auto Result = (*Function)->registerInfo().createVirtualRegister(Type);
- if (!Left || !Right || !Result || !constrainRegister(**Function, *Left, Type) ||
- !constrainRegister(**Function, *Right, Type) || !constrainRegister(**Function, *Result, Type))
+ if (!Left || !Right || !Result || !constrainRegister(**Function, *Left, Type, true) ||
+ !constrainRegister(**Function, *Right, Type, true) ||
+ !constrainRegister(**Function, *Result, Type, true))
return nullptr;
rcc::MachineIRBuilder Builder(**Function, Target);
if (!Builder.setInsertPoint(**Block))
@@ -230,7 +232,8 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta
[[nodiscard]] std::unique_ptr<rcc::MachineFunction> createRegisterOnlyFunction(
TestContext &Context, const rcc::TargetDescription &Target, rcc::GenericOpcode Generic,
- std::initializer_list<rcc::LLT> DefinitionTypes, std::initializer_list<rcc::LLT> UseTypes) {
+ std::initializer_list<rcc::LowLevelType> DefinitionTypes,
+ std::initializer_list<rcc::LowLevelType> UseTypes, bool FloatingValues = false) {
auto Function = rcc::MachineFunction::create(
"riscv_register_only",
rcc::MachineFunctionStableID::fromValue(1000 + static_cast<std::uint32_t>(Generic)));
@@ -246,17 +249,17 @@ createFloatBinaryFunction(TestContext &Context, const rcc::TargetDescription &Ta
auto Pending = Builder.buildInstr(rcc::opcode(Generic));
if (!Pending)
return nullptr;
- for (rcc::LLT Type : DefinitionTypes) {
+ for (rcc::LowLevelType Type : DefinitionTypes) {
auto Reg = (*Function)->registerInfo().createVirtualRegister(Type);
if (!Reg || !Pending->addDef(*Reg))
return nullptr;
}
- for (rcc::LLT Type : UseTypes) {
+ for (rcc::LowLevelType Type : UseTypes) {
auto Reg = (*Function)->registerInfo().createVirtualRegister(Type);
if (!Reg || !Pending->addUse(*Reg))
return nullptr;
}
- if (!Pending->build() || !constrainVirtualRegisters(**Function))
+ if (!Pending->build() || !constrainVirtualRegisters(**Function, FloatingValues))
return nullptr;
return std::move(*Function);
}
@@ -304,8 +307,8 @@ void testClassification(TestContext &Context) {
Context.expect(FloatBlock.has_value(), "floating constant block creation must succeed");
if (!FloatBlock || !(*FloatFunction)->appendBlock(**FloatBlock))
return;
- auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
+ auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
Context.expect(F32.has_value() && F64.has_value(),
"RV64GC floating constant types must be constructible");
if (!F32 || !F64)
@@ -442,8 +445,8 @@ void testNarrowIntegerSelection(TestContext &Context) {
"narrow integer selection must satisfy target descriptors");
}
- auto I7 = rcc::LLT::makeInteger(7);
- auto I24 = rcc::LLT::makeInteger(24);
+ auto I7 = rcc::LowLevelType::makeCategoryNeutralScalar(7);
+ auto I24 = rcc::LowLevelType::makeCategoryNeutralScalar(24);
if (!I7 || !I24)
return;
auto Compare = createCompareFunction(Context, *Target, rcc::GenericOpcode::G_ICMP, *I7, false,
@@ -494,11 +497,11 @@ void testScalarSelection(TestContext &Context) {
if (!Target)
return;
- auto I32 = rcc::LLT::makeInteger(32);
- auto I64 = rcc::LLT::makeInteger(64);
- auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
- auto I1 = rcc::LLT::makeInteger(1);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
Context.expect(I32 && I64 && F32 && F64 && I1, "scalar test types must be constructible");
if (!I32 || !I64 || !F32 || !F64 || !I1)
return;
@@ -546,11 +549,14 @@ void testScalarSelection(TestContext &Context) {
}
}
- auto FPExt = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPEXT, *F64, *F32);
- auto FPTrunc = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTRUNC, *F32, *F64);
- auto FPToSI = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTOSI, *I64, *F32);
- auto SIToFP = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_SITOFP, *F64, *I32);
- auto Bitcast = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_BITCAST, *I32, *F32);
+ auto FPExt =
+ createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPEXT, *F64, *F32, true, true);
+ auto FPTrunc =
+ createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTRUNC, *F32, *F64, true, true);
+ auto FPToSI =
+ createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_FPTOSI, *I64, *F32, false, true);
+ auto SIToFP =
+ createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_SITOFP, *F64, *I32, true, false);
if (FPExt) {
auto *Instruction = FPExt->firstBlock()->firstInstruction();
Context.expect((*GISel.Selector).select(*Instruction, *FPExt, *Target).has_value(),
@@ -583,14 +589,6 @@ void testScalarSelection(TestContext &Context) {
rcc::riscv::InstructionOpcode::FCVT_D_W)),
"sitofp must select FCVT.D.W");
}
- if (Bitcast) {
- auto *Instruction = Bitcast->firstBlock()->firstInstruction();
- Context.expect((*GISel.Selector).select(*Instruction, *Bitcast, *Target).has_value(),
- "float-to-integer bitcast must select");
- Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>(
- rcc::riscv::InstructionOpcode::FMV_X_W)),
- "float-to-integer bitcast must select FMV.X.W");
- }
}
void testComparisonsAndControl(TestContext &Context) {
@@ -598,9 +596,9 @@ void testComparisonsAndControl(TestContext &Context) {
Context.expect(Target.has_value(), "RV64GC target must be available for comparison selection");
if (!Target)
return;
- auto I64 = rcc::LLT::makeInteger(64);
- auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
if (!I64 || !F32 || !Pointer)
return;
@@ -739,10 +737,10 @@ void testCompositeScalarSelection(TestContext &Context) {
Context.expect(Target.has_value(), "RV64GC target must be available for composite selection");
if (!Target)
return;
- auto I1 = rcc::LLT::makeInteger(1);
- auto I32 = rcc::LLT::makeInteger(32);
- auto I64 = rcc::LLT::makeInteger(64);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!I1 || !I32 || !I64 || !F64)
return;
@@ -757,9 +755,9 @@ void testCompositeScalarSelection(TestContext &Context) {
auto IntegerSelect = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_SELECT,
{*I64}, {*I1, *I64, *I64});
auto FloatSelect = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_SELECT,
- {*F64}, {*I1, *F64, *F64});
+ {*F64}, {*I1, *F64, *F64}, true);
auto CopySign = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_FCOPYSIGN,
- {*F64}, {*F64, *F64});
+ {*F64}, {*F64, *F64}, true);
const std::array Functions{DivRem.get(), MultiplyHigh.get(), Minimum.get(), Absolute.get(),
IntegerSelect.get(), FloatSelect.get(), CopySign.get()};
for (rcc::MachineFunction *Function : Functions) {
@@ -805,16 +803,16 @@ void testOverflowSelection(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
if (!Target)
return;
- auto I1 = rcc::LLT::makeInteger(1);
- auto I32 = rcc::LLT::makeInteger(32);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!I1 || !I32 || !I64)
return;
const std::array Opcodes{rcc::GenericOpcode::G_UADDO, rcc::GenericOpcode::G_USUBO,
rcc::GenericOpcode::G_SADDO, rcc::GenericOpcode::G_SSUBO,
rcc::GenericOpcode::G_UMULO, rcc::GenericOpcode::G_SMULO};
for (rcc::GenericOpcode Generic : Opcodes) {
- const rcc::LLT Type = Generic == rcc::GenericOpcode::G_UMULO ? *I32 : *I64;
+ const rcc::LowLevelType Type = Generic == rcc::GenericOpcode::G_UMULO ? *I32 : *I64;
auto Function =
createRegisterOnlyFunction(Context, *Target, Generic, {Type, *I1}, {Type, Type});
Context.expect(Function != nullptr, "overflow fixture must be complete");
@@ -851,10 +849,10 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) {
if (!Target || !Function)
return;
auto Block = (*Function)->createBasicBlock();
- auto I1 = rcc::LLT::makeAnyScalar(1);
- auto I8 = rcc::LLT::makeAnyScalar(8);
- auto I64 = rcc::LLT::makeAnyScalar(64);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto I8 = rcc::LowLevelType::makeCategoryNeutralScalar(8);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
auto Size = rcc::MemorySize::fixed(1);
auto Align = rcc::Alignment::create(1);
if (!Block || !(*Function)->appendBlock(**Block) || !I1 || !I8 || !I64 || !Pointer || !Size ||
@@ -1003,8 +1001,8 @@ void testConstantExtensionPreservesLiveSource(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
auto Function = rcc::MachineFunction::create("riscv_live_constant_extension",
rcc::MachineFunctionStableID::fromValue(1300));
- auto I32 = rcc::LLT::makeAnyScalar(32);
- auto I64 = rcc::LLT::makeAnyScalar(64);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Target || !Function || !I32 || !I64)
return;
auto Block = (*Function)->createBasicBlock();
@@ -1048,8 +1046,8 @@ void testConstantExtensionPreservesLiveSource(TestContext &Context) {
void testIntegerCompareReusesConstantExtension(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
- auto I32 = rcc::LLT::makeAnyScalar(32);
- auto I64 = rcc::LLT::makeAnyScalar(64);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Target || !I32 || !I64)
return;
auto Function =
@@ -1109,9 +1107,9 @@ void testNarrowAnyExtBinaryArtifacts(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
auto Function = rcc::MachineFunction::create("riscv_narrow_binary_artifacts",
rcc::MachineFunctionStableID::fromValue(1301));
- auto I1 = rcc::LLT::makeAnyScalar(1);
- auto I32 = rcc::LLT::makeAnyScalar(32);
- auto I64 = rcc::LLT::makeAnyScalar(64);
+ auto I1 = rcc::LowLevelType::makeCategoryNeutralScalar(1);
+ auto I32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Target || !Function || !I1 || !I32 || !I64)
return;
auto Block = (*Function)->createBasicBlock();
@@ -1240,8 +1238,8 @@ void testAtomicSelection(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
if (!Target)
return;
- auto I64 = rcc::LLT::makeInteger(64);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
auto Size = rcc::MemorySize::fixed(8);
auto Align = rcc::Alignment::create(8);
if (!I64 || !Pointer || !Size || !Align)
@@ -1397,8 +1395,8 @@ void testUnsupportedTypes(TestContext &Context) {
(*GISel.Selector).canSelect(*WideInteger.Instruction, *WideInteger.Function, *Target);
Context.expect(!Selection && Selection.error().code() == rcc::ErrorCode::Unsupported,
"i128 arithmetic must produce an Unsupported diagnostic");
- Context.expect(!Selection && Selection.error().message().find("i128") != std::string::npos,
- "unsupported type diagnostics must name the rejected LLT");
+ Context.expect(!Selection && Selection.error().message().find("s128") != std::string::npos,
+ "unsupported type diagnostics must name the rejected LowLevelType");
}
auto Function = rcc::MachineFunction::create("unsupported_type",
rcc::MachineFunctionStableID::fromValue(100));
@@ -1407,7 +1405,7 @@ void testUnsupportedTypes(TestContext &Context) {
auto Block = (*Function)->createBasicBlock();
if (!Block || !(*Function)->appendBlock(**Block))
return;
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!F64)
return;
auto Result = (*Function)->registerInfo().createVirtualRegister(*F64);
@@ -1447,7 +1445,7 @@ void testVACopyLegalization(TestContext &Context) {
if (!Function)
return;
auto Block = (*Function)->createBasicBlock();
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
if (!Block || !Pointer || !(*Function)->appendBlock(**Block))
return;
auto Destination = (*Function)->registerInfo().createVirtualRegister(*Pointer);
@@ -1522,8 +1520,8 @@ void testVAArgLegalization(TestContext &Context) {
if (!Function)
return;
auto Block = (*Function)->createBasicBlock();
- auto Pointer = rcc::LLT::makePointer(0, 64);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Block || !Pointer || !I64 || !(*Function)->appendBlock(**Block))
return;
auto Destination = (*Function)->registerInfo().createVirtualRegister(*I64);
@@ -1611,8 +1609,8 @@ void testFrameIndexLegalization(TestContext &Context) {
if (!Function)
return;
auto Block = (*Function)->createBasicBlock();
- auto Pointer = rcc::LLT::makePointer(0, 64);
- auto OtherAddressSpace = rcc::LLT::makePointer(1, 64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
+ auto OtherAddressSpace = rcc::LowLevelType::makePointer(1, 64);
rcc::StackObjectDesc StackSlot;
StackSlot.Size = 8;
StackSlot.Align = *rcc::Alignment::create(8);
@@ -1653,9 +1651,9 @@ void testPointerArithmeticLegalization(TestContext &Context) {
Context.expect(Target.has_value(), "RV64GC target must be available for pointer legalization");
if (!Target)
return;
- auto Pointer = rcc::LLT::makePointer(0, 64);
- auto S64 = rcc::LLT::makeAnyScalar(64);
- auto S32 = rcc::LLT::makeAnyScalar(32);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
+ auto S64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto S32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
if (!Pointer || !S64 || !S32)
return;
auto Legal = createRegisterOnlyFunction(Context, *Target, rcc::GenericOpcode::G_PTR_ADD,
@@ -1686,8 +1684,8 @@ void testMemoryOffsetSelection(TestContext &Context) {
auto Block = (*Function)->createBasicBlock();
if (!Block || !(*Function)->appendBlock(**Block))
return;
- auto I64 = rcc::LLT::makeInteger(64);
- auto Pointer = rcc::LLT::makePointer(0, 64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto Pointer = rcc::LowLevelType::makePointer(0, 64);
if (!I64 || !Pointer)
return;
auto Result = (*Function)->registerInfo().createVirtualRegister(*I64);
diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp
index 89da994..0deebc6 100644
--- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp
+++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp
@@ -727,7 +727,7 @@ void testRISCVMemoryFoldingBoundary(TestContext &Context, const rcc::TargetDescr
if (!Function)
return;
rcc::MachineBasicBlock *Block = appendBlock(Context, *Function);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto Align = rcc::Alignment::create(8);
if (Block == nullptr || !I64 || !Align)
return;
@@ -995,8 +995,8 @@ void testPseudoPreparation(TestContext &Context, const rcc::TargetDescription &T
if (!Function)
return;
rcc::MachineBasicBlock *Block = appendBlock(Context, *Function);
- auto I64 = rcc::LLT::makeInteger(64);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (Block == nullptr || !I64 || !F64)
return;
auto Source = Function->registerInfo().createVirtualRegister(*I64);
diff --git a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
index 6daf58a..29bc756 100644
--- a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
+++ b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
@@ -84,7 +84,8 @@ struct FunctionFixture final {
return FunctionFixture{std::move(*Function), *Block};
}
-[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, rcc::LLT Type,
+[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function,
+ rcc::LowLevelType Type,
rcc::riscv::RegisterBank Bank,
rcc::riscv::RegisterClass Class) {
auto Reg = Function.registerInfo().createVirtualRegister(Type);
@@ -304,7 +305,7 @@ void testTargetHooks(TestContext &Context, const rcc::TargetDescription &Target)
void testRematerialization(TestContext &Context, const rcc::TargetDescription &Target) {
auto Fixture = createFunction("riscv-rematerialization", 2);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Fixture || !I64)
return;
auto Original = createVReg(*Fixture->Function, *I64, rcc::riscv::RegisterBank::GPR,
@@ -335,7 +336,7 @@ void testRematerialization(TestContext &Context, const rcc::TargetDescription &T
[[nodiscard]] rcc::Expected<FunctionFixture>
createSimpleAllocationFunction(const rcc::TargetDescription &Target, std::uint64_t ID) {
auto Fixture = createFunction("riscv-ra-" + std::to_string(ID), ID);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Fixture)
return std::unexpected(Fixture.error());
if (!I64)
@@ -448,7 +449,7 @@ void testFunctionReservedRegisters(TestContext &Context, const rcc::TargetDescri
[[nodiscard]] rcc::Expected<FunctionFixture>
createPressureFunction(const rcc::TargetDescription &Target, std::uint64_t ID) {
auto Fixture = createFunction("riscv-pressure-" + std::to_string(ID), ID);
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
if (!Fixture)
return std::unexpected(Fixture.error());
if (!I64)
diff --git a/backend/unittests/Target/RISCVSSAExitTest.cpp b/backend/unittests/Target/RISCVSSAExitTest.cpp
index 54a5911..1912666 100644
--- a/backend/unittests/Target/RISCVSSAExitTest.cpp
+++ b/backend/unittests/Target/RISCVSSAExitTest.cpp
@@ -54,7 +54,8 @@ private:
return rcc::RegisterClassID::fromValue(static_cast<std::uint32_t>(Class));
}
-[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function, rcc::LLT Type,
+[[nodiscard]] rcc::Expected<rcc::Register> createVReg(rcc::MachineFunction &Function,
+ rcc::LowLevelType Type,
rcc::riscv::RegisterBank Bank,
rcc::riscv::RegisterClass Class) {
auto Reg = Function.registerInfo().createVirtualRegister(Type);
@@ -219,9 +220,9 @@ void testBehaviorAndCopyLegality(TestContext &Context, const rcc::TargetDescript
Context.expect(Rewritten && *Rewritten && blockOperand(*Jump, 1)->Block == *Third,
"RV64GC branch target rewriting must update direct JAL operands");
- auto I64 = rcc::LLT::makeInteger(64);
- auto F64 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEEDouble);
- auto F32 = rcc::LLT::makeFloat(rcc::FloatSemantics::IEEESingle);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
+ auto F32 = rcc::LowLevelType::makeCategoryNeutralScalar(32);
if (!I64 || !F64 || !F32)
return;
auto GPR =
@@ -318,7 +319,7 @@ void testRV64GCCriticalEdge(TestContext &Context, const rcc::TargetDescription &
auto Merge = appendBlock(**Function);
if (!From || !Side || !Other || !Merge)
return;
- auto I64 = rcc::LLT::makeInteger(64);
+ auto I64 = rcc::LowLevelType::makeCategoryNeutralScalar(64);
auto X0 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X0);
if (!I64 || !X0)
return;
diff --git a/backend/utils/TableGen/Common/CodeGenInstruction.cpp b/backend/utils/TableGen/Common/CodeGenInstruction.cpp
index d06fbfc..cabe8d4 100644
--- a/backend/utils/TableGen/Common/CodeGenInstruction.cpp
+++ b/backend/utils/TableGen/Common/CodeGenInstruction.cpp
@@ -76,7 +76,7 @@ memoryRoleEnumerator(std::string_view Value) noexcept {
[[nodiscard]] std::optional<std::string_view>
instructionFlagEnumerator(std::string_view Value) noexcept {
- static constexpr std::array<std::pair<std::string_view, std::string_view>, 23> Flags = {{
+ static constexpr std::array<std::pair<std::string_view, std::string_view>, 24> Flags = {{
{"terminator", "Terminator"},
{"branch", "Branch"},
{"indirect_branch", "IndirectBranch"},
@@ -96,6 +96,7 @@ instructionFlagEnumerator(std::string_view Value) noexcept {
{"not_duplicable", "NotDuplicable"},
{"convergent", "Convergent"},
{"unmodeled_side_effects", "UnmodeledSideEffects"},
+ {"may_raise_fp_exception", "MayRaiseFPException"},
{"phi", "Phi"},
{"fake_use", "FakeUse"},
{"generic", "Generic"},